如何在“设置”对象的反序列化时更新WPF UI

我的目标是这样做:用户选择设置文件,读取设置并相应地更新UI。 显然也应该可以节省。

我的程序目前不是WPF / XAML,现在这样做意味着需要大量重复并在需要新设置时添加工作。

所以有人告诉我WPF / XAML是要走的路,我调查并喜欢它,但我仍然不确定如何做我想要的。 WPF / XAML的优点当然是数据绑定,但如果我想读取整个设置文件,我可能会用新的设置替换旧的设置对象。 我可以让WPF程序对此做出反应并根据某些给定的数据绑定更新字段吗?

我最感兴趣的是这是好的设计,如果不是 – 那是什么。

你当然可以。 首先,您的设置对象应该实现INotifyPropertyChanged接口。 这基本上会添加一个事件,每次调用属性设置器时都会调用该事件。 这种方式绑定到非依赖属性两种方式。 你真的不需要那个界面。 但是,如果您希望在第一个集合之后进行更改(其中所有属性都被读取)将在ui中反映出来,则需要该接口。

我通常使用基类

 public class PropertyChangedNotifier : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged { add { mPropertyChanged += value; } remove { mPropertyChanged -= value; } } protected virtual void RaisePropertyChanged(string aPropertyName) { PropertyChangedEventHandler handler = mPropertyChanged; if (handler != null) { var e = new PropertyChangedEventArgs(aPropertyName); handler(this, e); } } private PropertyChangedEventHandler mPropertyChanged; } 

您的设置现在应该从该类派生。

 class MySettings : PropertyChangedNotifier { public string UserName { get{return mUserName;} set{mUserName=value; RaisePropertyChanged("UserName");} } } 

现在对于ui,DataBinding始终与设置的DataContext

      

文本框将尝试从属性“UserName”中的当前set datacontext获取其值。 现在设置DataContext,我们可以在后面的主窗口代码中执行此操作。

 public MainWindow() { InitializeComponent(); DataContext = ReadMyUserSettings(); } 

如果您随时更改Datacontext,则ui会自动更新。 您对文本框的更改将被写回您的设置。 这也可以通过添加某种取消和保存工作流程来改进,这样,如果用户点击取消,则不会更改设置。 请参阅IEditableObjectBindingGroup

希望能给你一个粗略的想法,它是如何工作的。

以下是我将如何使用MVVM模式在c#类伪代码中使用一个非常简单的示例。

首先,我定义了我的模型,它定义了我的配置并进行了序列化/反序列化。 我更喜欢使用NetDataContractSerializer来做这件事。

 [DataContract] public sealed class Person { [DataMember] public string Name {get;set;} [DataMember] public int Age {get;set;} } 

我的ViewModel将拥有一个公共属性,用于保存此配置的当前实例

 public sealed class ViewModel : DependencyObject { #region Person ///  /// The  for . ///  public static readonly DependencyProperty TextProperty = DependencyProperty.Register( PersonPropertyName, typeof(Person), typeof(ViewModel), new UIPropertyMetadata(null)); ///  /// The name of the  . ///  public const string PersonPropertyName = "Person"; ///  /// The Person ///  public string Person { get { return (Person)GetValue(PersonProperty ); } set { SetValue(PersonProperty , value); } } #endregion // snip 

在我的ViewModel我还有一个用于加载和保存配置的ICommand 。 这里有很多关于ICommand的通用实现的问题, CanExecuteExecute委托给ViewModel。

在UI中,您只需通过ViewModel绑定到配置模型的公共属性。

          

因为配置模型保存在ViewModel的公共DependencyProperty中,所以当您替换它时,UI将使用新值自动更新。 当然,您可以使用INotifyPropertyChanged作为通知UI绑定更新的替代方法,但我更喜欢保持简单。