Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在反序列化“WPF”时更新WPF UI;“设置”;对象_C#_Wpf_Xaml_Serialization_Deserialization - Fatal编程技术网

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

C# 如何在反序列化“WPF”时更新WPF UI;“设置”;对象,c#,wpf,xaml,serialization,deserialization,C#,Wpf,Xaml,Serialization,Deserialization,我的目标是这样做:用户选择设置文件,读取设置并相应地更新UI。显然,储蓄也是可能的 我的程序目前不是WPF/XAML,现在这样做意味着在需要新设置时需要大量重复和添加工作 所以有人告诉我WPF/XAML是一个不错的选择,我仔细研究了它并喜欢它,但我仍然不知道如何做我想要的。WPF/XAML的优点当然是数据绑定,但是如果我想读取整个设置文件,我可能会用一个新的对象替换旧的设置对象。我可以让WPF程序对此做出反应并根据一些给定的数据绑定更新字段吗 我最感兴趣的是这是否是好的设计,如果不是,是什么。当

我的目标是这样做:用户选择设置文件,读取设置并相应地更新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}" />