如何在“设置”对象的反序列化时更新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会自动更新。 您对文本框的更改将被写回您的设置。 这也可以通过添加某种取消和保存工作流程来改进,这样,如果用户点击取消,则不会更改设置。 请参阅IEditableObject
和BindingGroup
。
希望能给你一个粗略的想法,它是如何工作的。
以下是我将如何使用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的通用实现的问题, CanExecute
和Execute
委托给ViewModel。
在UI中,您只需通过ViewModel绑定到配置模型的公共属性。
因为配置模型保存在ViewModel的公共DependencyProperty中,所以当您替换它时,UI将使用新值自动更新。 当然,您可以使用INotifyPropertyChanged作为通知UI绑定更新的替代方法,但我更喜欢保持简单。