子成员属性更改时触发PropertyChanged

时间:2018-06-19 08:21:53

标签: c# wpf dependency-properties inotifypropertychanged

我有一个WPF控件应该很容易(重新)使用。为此,我有一个自定义类型,包含控件应该表示的所有设置,并通过DependencyProperty绑定它。

但是,每当我更改控件中的一个成员时,父控件都会获取成员中的更改(通过其他方式进行评估时),但PropertyChanged-Callback永远不会在父控件中触发。

public class Setting
{
    public int Prop {get;set;}
    //Other Properties, Constructor & Copy Constructor, etc.
    public override bool Equals(object obj)
    {
        if (!(obj is Setting other)) return false;
        return Prop == other.Prop;
    }
}

public class SettingControl : UserControl, INotifyPropertyChanged
{
    public static readonly DependencyProperty SettingProperty = DependencyProperty.Register
                (nameof(Settings), typeof(Setting), typeof(SettingControl),
                    new PropertyMetadata(default(Setting), OnValuePropertyChanged));

    public Setting Settings
        {
            get => (Setting)GetValue(SettingProperty);
            set
            {
                SetValue(SettingProperty, value);
                OnPropertyChanged(nameof(Settings));
            }
        }

    public int Prop
        {
            get => ((Setting)GetValue(SettingProperty))?.Prop ?? 0;
            set
            {
                //Does not work:
                var temp = (Setting)GetValue(SettingProperty);
                temp.Prop = value;
                Settings = temp;
                OnPropertyChanged(nameof(Prop));

                //Does not work:
                Settings.Prop = value;
                OnPropertyChanged(nameof(Prop));
                OnPropertyChanged(nameof(Settings));

                //**Does work**, and triggers the OnSettingChanged in the parent control, 
                //but is simply not great memory usage
                Settings = new Setting(Settings){ Prop = value };
                OnPropertyChanged(nameof(Prop));
            }
        }
}

//Relevant snippet from parent Control ViewModel:
public static readonly DependencyProperty SettingProperty =
        DependencyProperty.Register(nameof(Settings), typeof(Setting), typeof(ControlViewModel),
            new PropertyMetadata(default(Setting), (d, e) => ((ControlViewModel)d).OnSettingChanged()));
//OnSettingChanged() is never called

public Setting Settings
    {
        get => (Setting)GetValue(SettingProperty);
        set //Set is never called when the member properties are changed
        {
            SetValue(SettingProperty, value);
            OnPropertyChanged(nameof(Settings));
        }
    }

//Relevant snippet from parent xaml:
<local:SettingControl Width="300"
                      Settings="{Binding Path=Settings, Mode=TwoWay}"/>
// UpdateSourceTrigger=PropertyChanged doesn't help here either

当然,一个明显的解决方案是将Setting类包装到SettingViewModel中,或者将其实现为ViewModel本身(小测试无论如何都没有显示结果)。然而,这会使控件的使用更加困难,并且在某种程度上打破MVVM(已经超过这个)。 Setting类中还有一些用于序列化的XML内容,我不想搞砸。

我注意到的一件事是,如果Equals中的Setting函数被编码为始终返回true两种设置通常不起作用的成员属性的方式,突然工作并触发所期望的行为。

先谢谢。

0 个答案:

没有答案