C# 如何在反序列化“WPF”时更新WPF UI;“设置”;对象
我的目标是这样做:用户选择设置文件,读取设置并相应地更新UI。显然,储蓄也是可能的 我的程序目前不是WPF/XAML,现在这样做意味着在需要新设置时需要大量重复和添加工作 所以有人告诉我WPF/XAML是一个不错的选择,我仔细研究了它并喜欢它,但我仍然不知道如何做我想要的。WPF/XAML的优点当然是数据绑定,但是如果我想读取整个设置文件,我可能会用一个新的对象替换旧的设置对象。我可以让WPF程序对此做出反应并根据一些给定的数据绑定更新字段吗C# 如何在反序列化“WPF”时更新WPF UI;“设置”;对象,c#,wpf,xaml,serialization,deserialization,C#,Wpf,Xaml,Serialization,Deserialization,我的目标是这样做:用户选择设置文件,读取设置并相应地更新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,数据绑定总是与集合DataContext
相关
<Window
x:Class="MyApp.MainWindow">
<StackPanel>
<TextBox Text="{Binding UserName}"/>
</StackPanel>
</Window>
如果您随时更改Datacontext,ui将自动更新。
您对文本框的更改将写回您的设置。这也可以通过添加某种类型的“取消”和“保存”工作流来改进,以便在用户单击“取消”时不会更改您的设置。请参见IEditableObject
和BindingGroup
希望这能给你一个大致的想法,它是如何工作的。下面是我将如何做到这一点,使用一个非常简单的例子,类似于使用MVVM模式的c伪代码 首先,我要定义我的模型,这些模型定义了我的配置并被序列化/反序列化。我更喜欢使用 我的ViewModel将具有一个公共属性,该属性保存此配置的当前实例
public sealed class ViewModel : DependencyObject
{
#region Person
/// <summary>
/// The <see cref="DependencyProperty"/> for <see cref="Person"/>.
/// </summary>
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
PersonPropertyName,
typeof(Person),
typeof(ViewModel),
new UIPropertyMetadata(null));
/// <summary>
/// The name of the <see cref="Person"/> <see cref="DependencyProperty"/>.
/// </summary>
public const string PersonPropertyName = "Person";
/// <summary>
/// The Person
/// </summary>
public string Person
{
get { return (Person)GetValue(PersonProperty ); }
set { SetValue(PersonProperty , value); }
}
#endregion
// snip
由于配置模型保存在ViewModel的公共从属属性中,因此在替换它时,UI会自动更新为新值。当然,您可以使用INotifyPropertyChanged作为通知UI绑定更新的替代方法,但我更喜欢保持简单。数据绑定早在wpf/xaml之前就存在了-我个人需要更多的理由在堆栈之间移动“设置”。。。
[DataContract]
public sealed class Person
{
[DataMember]
public string Name {get;set;}
[DataMember]
public int Age {get;set;}
}
public sealed class ViewModel : DependencyObject
{
#region Person
/// <summary>
/// The <see cref="DependencyProperty"/> for <see cref="Person"/>.
/// </summary>
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
PersonPropertyName,
typeof(Person),
typeof(ViewModel),
new UIPropertyMetadata(null));
/// <summary>
/// The name of the <see cref="Person"/> <see cref="DependencyProperty"/>.
/// </summary>
public const string PersonPropertyName = "Person";
/// <summary>
/// The Person
/// </summary>
public string Person
{
get { return (Person)GetValue(PersonProperty ); }
set { SetValue(PersonProperty , value); }
}
#endregion
// snip
<Window x:Class="Herp.DerpWindow" SnipXamlForBrevity="true">
<Window.DataContext>
<ViewModel xmlns="clr-namespace:Herp" />
</Window.DataContext>
<!-- and later... -->
<Label>The Person in Question:</Label>
<TextBlock Text="{Binding Person.Name}" />
<Label>Age</Label>
<TextBlock Text="{Binding Person.Age}" />