天天看点

创建相互依赖(影响)的WPF属性

昨天在网上看到一个网友问如何在WPF里面实现相互依赖的属性,例如下面一个类:

using System;

public class RtdField

{

    #region SizeX

    public Double X1

    {

        get { return x1; }

        set

        {

            x1 = value;

            OnPropertyChanged("X1");

            OnPropertyChanged("X");

            OnPropertyChanged("OffsetX");

        }

    }

    private Double x1;

    public Double X2

        get { return x2; }

            x2 = value;

            OnPropertyChanged("X2");

    private Double x2;

    public double X

        get { return x1 + x2; }

            double hx = value / 2.0;

            double ox = OffsetX;

            x1 = hx - ox;

            x2 = hx + ox;

            OnPropertyChanged("X1");

    public double OffsetX

        get { return (x2 - x1) / 2.0; }

        set

            double hx = X / 2.0;

            double ox = value;

    #endregion

}

需要实现,如果OffsetX发生了变化, 那么X1和X2跟着发生变化,然而X1或者X2发生变化,那么X和OffsetX的值也发生变化。

我第一个想到的方法就是使用WPF的数据绑定,使用多重绑定(MultiBinding)和对应的转换器(Converter)来做,因为数据绑定支持双向绑定(Mode.TwoWay),即一个属性变化了,依赖它的其他属性都跟着变化,而依赖属性变化了,原先的属性也会跟着发生变化。

使用数据绑定的方法,其实就是将OffsetX和X属性绑定到X1和X2上面,数据源是对象自己,然后把X和OffsetX里面的Set函数移到对应的值转换器(ValueConverter)里面就好了。

代码:

public partial class Window1 : Window

    public Window1()

        InitializeComponent();

        TestClass tc = new TestClass();

        tc.X1 = 1;

        tc.X = 2.4;

public class TestClass : DependencyObject

    public double X1

        get { return (double)GetValue(X1Property); }

        set { SetValue(X1Property, value); }

    public static readonly DependencyProperty X1Property =

        DependencyProperty.Register("X1", typeof(double), typeof(TestClass), newUIPropertyMetadata(0.0));

    public double X2

        get { return (double)GetValue(X2Property); }

        set { SetValue(X2Property, value); }

    public static readonly DependencyProperty X2Property =

        DependencyProperty.Register("X2", typeof(double), typeof(TestClass), newUIPropertyMetadata(0.0));

        get { return (double)GetValue(XProperty); }

        set { SetValue(XProperty, value); }

    public static readonly DependencyProperty XProperty =

        DependencyProperty.Register("X", typeof(double), typeof(TestClass), newUIPropertyMetadata(0.0));

        get { return (double)GetValue(OffsetXProperty); }

        set { SetValue(OffsetXProperty, value); }

    public static readonly DependencyProperty OffsetXProperty =

        DependencyProperty.Register("OffsetX", typeof(double), typeof(TestClass), newUIPropertyMetadata(0.0));

    public TestClass()

        MultiBinding binding = new MultiBinding();

        binding.Bindings.Add(new Binding("X1")

            RelativeSource = RelativeSource.Self,

            // 下面这个模式一定要设置,否则

            // X属性更改了,虽然会调用X1X2ToXConverter.ConvertBack

            // 函数,但是生成的值不会放回到X1和X2里面。

            Mode = BindingMode.TwoWay

        });

        binding.Bindings.Add(new Binding("X2")

            Mode = BindingMode.TwoWay

        binding.Converter = new X1X2ToXConverter();

        // 下面这个模式也要设置,否则X属性更改不会

        // 让WPF自动调用X1X2ToXConverter.ConvertBack函数

        binding.Mode = BindingMode.TwoWay;

        binding.ConverterParameter = this;

        BindingOperations.SetBinding(this, XProperty, binding);

        binding = new MultiBinding();

            Mode = BindingMode.TwoWay

        binding.Converter = new X1X2ToOffsetXConverter();

        BindingOperations.SetBinding(this, OffsetXProperty, binding);

public class X1X2ToXConverter : IMultiValueConverter

    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        return (double)values[0] + (double)values[1];

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)

        double hx = (double)value / 2.0;

        var tc = parameter as TestClass;

        double ox = tc.OffsetX;

        var result = new object[] {

                hx - ox,

                hx + ox};

        return result;

public class X1X2ToOffsetXConverter : IMultiValueConverter

        return ((double)values[1] - (double)values[0]) / 2.0;

        double hx = ((TestClass)value).X / 2.0;

        double ox = (double)value;

本文转自 donjuan 博客园博客,原文链接: http://www.cnblogs.com/killmyday/archive/2009/09/18/1569569.html  ,如需转载请自行联系原作者