【问题标题】:Binding two Dependency properties in WPF在 WPF 中绑定两个依赖属性
【发布时间】:2011-12-03 10:00:29
【问题描述】:

我声明了两个依赖属性: 首先,Color 类型的 FilterColor 第二个 FilterBrush 类型为 Brush。 当 FilterBrush.Color 属性发生变化时,我需要更新 FilterColor 的值,而当 FilterColor 属性发生变化时,我需要更新 FilterBrush.Color 的值。 怎么实现?

【问题讨论】:

  • 如果您向我们展示 XAML 或 C#,我们可以向您展示如何连接它们

标签: c# wpf binding dependency-properties


【解决方案1】:

您在哪里定义了这些属性:在视图模型中还是在控件中?

如果它在视图模型中,您应该使用 INotifyPropertyChanged 而不是这样的依赖属性:

Color _filterColor;

public Color FilterColor
{
    get
    {
        return _filterColor;
    }
    {
        if (_filterColor != value)
        {
            _filterColor = value;
            RaisePropertyChanged(() => FilterColor);

            _OnFilterColorChanged();
        }
}

void _OnFilterColorChanged()
{
    _filterBrush= ...
    RaisePropertyChanged(() => FilterBrush);
}

Brush _filterBrush;

public Brush FilterBrush
{
    get
    {
        return _filterBrush;
    }
    {
        if (_filterBrush != value)
        {
            _filterBrush = value;
            RaisePropertyChanged(() => FilterBrush);

            _OnFilterBrushChanged();
        }
}

void _OnFilterBrushChanged()
{
    _filterColor= ...
    RaisePropertyChanged(() =. FilterColor);
}

如果它在控制中,请执行以下操作:

public Color FilterColor
{
    get { return (Color)GetValue(FilterColorProperty); }
    set { SetValue(FilterColorProperty, value); }
}
public static readonly DependencyProperty FilterColorProperty =
    DependencyProperty.Register("FilterColor", typeof(Color), typeof(MainWindow), new UIPropertyMetadata(Colors.Transparent, new PropertyChangedCallback(_OnFilterColorPropertyChanged)));

static void _OnFilterColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var mw = d as MainWindow;

    Color oldValue = (Color)e.OldValue;
    Color newValue = (Color)e.NewValue;

    if (null != mw && oldValue != newValue)
    {
        mw._OnFilterColorChanged(oldValue, newValue);
    }
}

bool _isFilterColorUpdating = false;

void _OnFilterColorChanged(Color oldValue, Color newValue)
{
    if (_isFilterBrushUpdating )
        return;

    _isFilterColorUpdating = true;
    Brush = ...
    _isFilterColorUpdating = false;
}

public Brush FilterBrush
{
    get { return (Brush)GetValue(FilterBrushProperty); }
    set { SetValue(FilterBrushProperty, value); }
}
public static readonly DependencyProperty FilterBrushProperty =
    DependencyProperty.Register("FilterBrush", typeof(Brush), typeof(MainWindow), new UIPropertyMetadata(Brushs.Transparent, new PropertyChangedCallback(_OnFilterBrushPropertyChanged)));

static void _OnFilterBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var mw = d as MainWindow;

    Brush oldValue = (Brush)e.OldValue;
    Brush newValue = (Brush)e.NewValue;

    if (null != mw && oldValue != newValue)
    {
        mw._OnFilterBrushChanged(oldValue, newValue);
    }
}

bool _isFilterBrushUpdating = false;
void _OnFilterBrushChanged(Brush oldValue, Brush newValue)
{
    if (_isFilterColorUpdating )
        return;

    _isFilterBrushUpdating = true;
    Color = ...
    _isFilterBrushUpdating = false;
}

请注意,最后一种方式只是 hack,它真的很糟糕,我更喜欢第一种方式。

【讨论】:

    【解决方案2】:

    您可以在 DependencyProperty 定义中执行此操作,也可以在之后使用 DependencyPropertyDescriptor 执行此操作

    例如....

    DependencyProperty 定义:

    public static readonly DependencyProperty FilterColorProperty =
        DependencyProperty.Register("FilterColor", typeof(Color),
        typeof(MyUserControl),
        new PropertyMetadata(Colors.White, FilterColorChanged));
    
    public static void FilterColorChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (!(obj is MyUserControl))
            return;
    
        MyUserControl ctrl = (MyUserControl)obj;
        var brush = ctrl.GetBrushProperty();
    
        if (brush.Color != (Color)e.NewValue)
            brush.Color = (Color)e.NewValue;
    }
    

    依赖属性描述符:

    DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(
        MyUserControl.FilterColorProperty, typeof(MyUserControl));
    
    if (dpd != null) 
        dpd.AddValueChanged(this, delegate { FilterColor_Changed(); });
    
    ...
    
    private void FilterColor_Changed()
    {
        Color filterColor = GetFilterColor(this);
        var brush = GetBrush(this);
        if (filterColor != brush.Color)
            brush.Color = filterColor;
    }
    

    我可能有一些语法错误...我没有编译器来检查代码

    【讨论】:

      【解决方案3】:

      使用 TwoWay 绑定绑定您的两个属性,如果您在 UI 中更改一个,则在属性设置器中更改另一个,反之亦然,并使用 INotifyPropertyChanged 通知您的 UI 该属性已更改。

      【讨论】:

      • PropertyChanged 仅在 CLR 属性的情况下才需要引发。对于 DP,您不必显式引发 PropertyChanged 事件。
      • 哦,是的,你是对的,我忘记了。 :D 似乎我尝试使用 MVVM。 :D
      猜你喜欢
      • 2012-11-08
      • 2014-08-31
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多