开发者

Logically combine dependency properties

I'm using C# 4.0 and have created a DependencyObject MyView.

In MyView, I have two DependencyProperties, PropA and PropB, both are booleans.

I want a third DependencyProperty, PropC, also a bool, and simply put, should always give me (PropA || PropB).

  1. What is the best way to accomplish this?
  2. I was also thinking of making PropC a readonly Depend开发者_Go百科encyProperty, but have read about issues with binding to readonly dp's (WPF ReadOnly Dependency Properties using MVVM)


You can use the Dependency Property changed callback for PropA and PropB to set the value for PropC (don't use the CLR property wrapper for the Dependency Properties as they are never guaranteed to be called).

If you have these three DP's

public static readonly DependencyProperty PropAProperty =
    DependencyProperty.Register("PropA",
    typeof(bool),
    typeof(MyView),
    new PropertyMetadata(false, PropAPropertyChanged));

public static readonly DependencyProperty PropBProperty =
    DependencyProperty.Register("PropB",
    typeof(bool),
    typeof(MyView),
    new PropertyMetadata(false, PropBPropertyChanged));

public static readonly DependencyProperty PropCProperty =
    DependencyProperty.Register("PropC",
    typeof(bool),
    typeof(MyView),
    new PropertyMetadata(false));

public bool PropA
{
    get { return (bool)this.GetValue(PropAProperty); }
    set { this.SetValue(PropAProperty, value); }
}
public bool PropB
{
    get { return (bool)this.GetValue(PropBProperty); }
    set { this.SetValue(PropBProperty, value); }
}
public bool PropC
{
    get { return (bool)this.GetValue(PropCProperty); }
    set { this.SetValue(PropCProperty, value); }
}

you can use the property changed callback like this

private static void PropAPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
    MyView myView = source as MyView;
    myView.OnPropChanged();
}
private static void PropBPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
    MyView myView = source as MyView;
    myView.OnPropChanged();
}
public void OnPropChanged()
{
    PropC = PropA || PropB;
}

This way, you'll always update the value of PropC everytime PropA or PropB changes

Also, PropC doesn't need to be a DP, it can be a normal CLR property if you implement INotifyPropertyChanged. Then the implementation can look like this instead

public void OnPropChanged()
{
    OnPropertyChanged("PropC");
}   
public bool PropC
{
    get
    {
        return PropA || PropB;
    }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

You could also bind PropC to PropA and PropB with a MultiBinding. Let me know if you want an example of this as well


The linked web page is for an unusual situation, a "push" binding. That is, a one-way-to-source binding was attempted on the read-only property, not on another property trying to bind to it. By contrast, if you want your property to be bindable to other properties using a one-way binding expression on the other property, then you can use a read-only dependency property without any issues.

Edit:

Here is an example:

<Grid>
    <Grid.Resources>
        <local:MyObject x:Key="myObject" PropertyA="True" PropertyB="False"/>
    </Grid.Resources>
    <StackPanel DataContext="{StaticResource myObject}">
        <CheckBox IsChecked="{Binding PropertyA}"  Content="PropertyA"/>
        <CheckBox IsChecked="{Binding PropertyB}"  Content="PropertyB"/>
        <CheckBox IsChecked="{Binding PropertyC, Mode=OneWay}" IsEnabled="False"  Content="PropertyC"/>
    </StackPanel>
</Grid>

and the dependency properties, one of which is read-only:

public class MyObject : DependencyObject
{
    public bool PropertyA
    {
        get { return (bool)GetValue(PropertyAProperty); }
        set { SetValue(PropertyAProperty, value); }
    }

    public static readonly DependencyProperty PropertyAProperty =
        DependencyProperty.Register("PropertyA", typeof(bool), typeof(MyObject), new UIPropertyMetadata(false, OnPropertyAOrBChanged));

    public bool PropertyB
    {
        get { return (bool)GetValue(PropertyBProperty); }
        set { SetValue(PropertyBProperty, value); }
    }

    public static readonly DependencyProperty PropertyBProperty =
        DependencyProperty.Register("PropertyB", typeof(bool), typeof(MyObject), new UIPropertyMetadata(false, OnPropertyAOrBChanged));

    public bool PropertyC
    {
        get { return (bool)GetValue(PropertyCProperty); }
        set { SetValue(PropertyCPropertyKey, value); }
    }

    private static readonly DependencyPropertyKey PropertyCPropertyKey =
        DependencyProperty.RegisterReadOnly("PropertyC", typeof(bool), typeof(MyObject), new UIPropertyMetadata());
    public static readonly DependencyProperty PropertyCProperty = PropertyCPropertyKey.DependencyProperty;

    private static void OnPropertyAOrBChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var myObject = d as MyObject;
        myObject.PropertyC = myObject.PropertyA || myObject.PropertyB;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜