通过多个类传播属性更改

时间:2016-08-31 09:39:39

标签: c# properties

我试图找出如何通过多个类正确传递属性。我知道我可以在每个类中实现INotifyPropertyChanged并监听属性的更改,但这似乎是相当多的不必要的代码。

情况:
我有一个类(让我们称之为Class1)有两个依赖属性:FilterStatement(String)和Filter(Filter类)。设置语句会影响过滤器,反之亦然。
但是,语句和过滤器之间的转换逻辑不在Class1中,而在Class3中 - Class1并不直接知道。在两者之间只有Class2才能通过更改。 (你可以想象1到3级的视图模型,模型和存储库,虽然在实际情况下这并不完全匹配)。

public class Class1
{
    public static readonly DependencyProperty FilterProperty = DependencyProperty.Register(
        "Filter",
        typeof(Filter),
        typeof(Class1),
        new FrameworkPropertyMetadata(null));

    public static readonly DependencyProperty FilterStatementProperty = DependencyProperty.Register(
        "FilterStatement",
        typeof(String),
        typeof(Class1),
        new FrameworkPropertyMetadata(null));

    public Filter Filter
    {
        get { return (Filter)GetValue(FilterProperty); }
        set { SetValue(FilterProperty, value); }
    }

    public string FilterStatement
    {
        get { return (string)GetValue(FilterStatementProperty); }
        set { SetValue(FilterStatementProperty, value); }
    }

    public Class2 MyClass2Instance { get; set; }
}

public class Class2
{
    public Class3 MyClass3Instance { get; set; }

    public void ChangeClass3Instance(object someParam) {
        ...  // this can change the instance of MyClass3Instance and is called frome somewhere else
        // when changed, the new Class3 instance has to get the property values of Class1
    }
}

public class Class3
{
    private Filter _filter; // here is where the filter set in Class 1 or determined by the statement set in class 1 has to be put

    public string MyFilterToStatementConversionMemberFunction(Filter filter)
    {
        ...
    }

    public Filter MyStatementToFilterConversionMemberFunction(string statement)
    {
        ...
    }
}

我天真的解决方案是在所有三个类中复制属性,在INotifyPropertyChangedClass2中实施Class3并听取更改,将所有内容传播到Class3并在结果中返回Class1。难道没有更好的解决方案吗?

2 个答案:

答案 0 :(得分:3)

实际上,虽然Class1不是控件(假设它是ViewModel),但我没有理由将其属性设为DependencyProperty,因为INotifyPropertyChanged的实现应该是足够。 但是,DependencyProperty的实施也应该有效:

public class Class1
{
    public static readonly DependencyProperty FilterProperty =
        DependencyProperty.Register(
            nameof(Filter),
            typeof(Filter),
            typeof(Class1),
            new PropertyMetadata(OnPropertyChanged));

    public static readonly DependencyProperty FilterStatementProperty =
        DependencyProperty.Register(
            nameof(FilterStatement),
            typeof(string),
            typeof(Class1),
            new PropertyMetadata(OnPropertyChanged));

    public Filter Filter
    {
        get { return (Filter)GetValue(FilterProperty); }
        set { SetValue(FilterProperty, value); }
    }

    public string FilterStatement
    {
        get { return (string)GetValue(FilterStatementProperty); }
        set { SetValue(FilterStatementProperty, value); }
    }

    public Class2 MyClass2Instance { get; set; }

    private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var c = (Class1)d;
        if (c.MyClass2Instance?.MyClass3Instance != null)
        {
            if (e.Property == FilterProperty)
            {
                c.FilterStatement = c.MyClass2Instance.MyClass3Instance.MyFilterToStatementConversionMemberFunction((Filter)e.NewValue);
            }
            else if (e.Property == FilterStatementProperty)
            {
                c.Filter = c.MyClass2Instance.MyClass3Instance.MyStatementToFilterConversionMemberFunction((string)e.NewValue);
            }
        }
    }
}

请注意,Filter.Equals应该正确实现,Class3的转换方法应返回相等参数的相等值。

答案 1 :(得分:0)

I think you complicate this too much. Observable pattern is better fit to user interface implementation. Why don't you code in Class3 logic which set all propertis in Class1 ? I thnik that overload setter FilterStatmentand Filter in Class1, which is ViewModel is good solution as well. As simpler solution as better.