zoukankan      html  css  js  c++  java
  • 创建相互依赖(影响)的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; }

            set

            {

                x2 = value;

                OnPropertyChanged("X2");

                OnPropertyChanged("X");

                OnPropertyChanged("OffsetX");

            }

        }

        private Double x2;

     

     

        public double X

        {

            get { return x1 + x2; }

            set

            {

                double hx = value / 2.0;

                double ox = OffsetX;

                x1 = hx - ox;

                x2 = hx + ox;

                OnPropertyChanged("X1");

                OnPropertyChanged("X2");

                OnPropertyChanged("X");

            }

        }

        public double OffsetX

        {

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

            set

            {

                double hx = X / 2.0;

                double ox = value;

                x1 = hx - ox;

                x2 = hx + ox;

                OnPropertyChanged("X1");

                OnPropertyChanged("X2");

                OnPropertyChanged("OffsetX");

            }

        }

        #endregion

    }

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

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

    使用数据绑定的方法,其实就是将OffsetXX属性绑定到X1X2上面,数据源是对象自己,然后把XOffsetX里面的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), new UIPropertyMetadata(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), new UIPropertyMetadata(0.0));

     

        public double X

        {

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

            set { SetValue(XProperty, value); }

        }

     

        public static readonly DependencyProperty XProperty =

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

     

        public double OffsetX

        {

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

            set { SetValue(OffsetXProperty, value); }

        }

     

        public static readonly DependencyProperty OffsetXProperty =

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

     

        public TestClass()

        {

            MultiBinding binding = new MultiBinding();

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

            {

                RelativeSource = RelativeSource.Self,

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

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

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

                Mode = BindingMode.TwoWay

            });

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

            {

                RelativeSource = RelativeSource.Self,

                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();

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

            {

                RelativeSource = RelativeSource.Self,

                Mode = BindingMode.TwoWay

            });

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

            {

                RelativeSource = RelativeSource.Self,

                Mode = BindingMode.TwoWay

            });

            binding.Converter = new X1X2ToOffsetXConverter();

            binding.Mode = BindingMode.TwoWay;

            binding.ConverterParameter = this;

            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;

        }

     

        #endregion

    }

     

    public class X1X2ToOffsetXConverter : IMultiValueConverter

    {

        #region IMultiValueConverter Members

     

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

        {

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

        }

     

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

        {

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

            double ox = (double)value;

            var result = new object[] {

                    hx - ox,

                    hx + ox};

     

            return result;

        }

     

        #endregion

    }

     

  • 相关阅读:
    SQlServer 从系统表 sysobjects 中获取数据库中所有表或存储过程等对象
    Win7 Print Spooler服務自动关闭
    C# 数据流操作 Stream 相关
    GRUB引导故障解决
    RAID配置层+配额
    磁盘一
    权限管理及归属
    cenos7关闭防火墙 安全机制
    linux用户管理-----账号管理和权限归属设置
    yum 仓构建,源代码安装
  • 原文地址:https://www.cnblogs.com/killmyday/p/1569569.html
Copyright © 2011-2022 走看看