【问题标题】:How to databind two dependency properties belonging to two different controls?如何对属于两个不同控件的两个依赖属性进行数据绑定?
【发布时间】:2011-10-31 22:14:41
【问题描述】:

另外:如何通过两个依赖属性的数据绑定来订阅 INotifyPropertyChanged 定义的 PropertyChanged 事件?

我的主窗口中有两个单独的用户控件。一个控件包含影响另一个控件的参数,我们称它为显示控件。我希望参数控件充当显示控件的数据源,以便当我更改参数控件中的参数时,显示控件会监听并做出相应的反应。

为此,我创建了一个实现 INotifyPropertyChanged 的​​类,该类存储这些参数并在两个控件中创建了此类类型的依赖项属性。我期待如果我将一个控件属性绑定到另一个控件属性,我会得到所需的行为,但不幸的是,我错过了一些重要的东西,因为显示控件没有反应。

在使用调试器仔细检查时,我注意到当属性发生更改时,我的事件 PropertyChangedEventHandler PropertyChanged 始终为空,并且我读到的所有内容都表明没有人在监听。

因为显示控件是实时创建的,所以我必须像这样以编程方式创建绑定:

var DispayControlValuesBinding = new Binding();
DispayControlValuesBinding.Source = DisplayControlsControl;
DispayControlValuesBinding.Path = new PropertyPath("DisplayControlValues");
DispayControlValuesBinding.Mode = BindingMode.OneWay;
DispayControlValuesBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
DispayControlValuesBinding.NotifyOnSourceUpdated = true;
//        
graph.SetBinding(Graph.DisplayControlValuesProperty, DisplayControlValuesBinding);

两个控件都有一个名为 DispayControlValues 的依赖属性。我尝试将 DisplayControlControl 的 DisplayControlValues 属性绑定到图形控件的 DisplayControlValues 属性。

当应用程序运行时,它会初始化参数控件,然后根据用户请求以编程方式创建显示控件并进行绑定。然后我在参数控件中更改了一个值,这是由实现 INotifyPropertyChanged 接口的参数类捕获的,但是由于没有人在侦听,因此事件处理程序为空,这就是我卡住的地方。

非常感谢您的帮助!

以下是应要求提供的更多详细信息:

我有一个用户控件,它公开了改变另一个控件行为的参数。此控件有一个包含参数详细信息并实现 INotifyPropertyChanged 接口的依赖属性。

这是课程:

public class ZoomGraphControlValues : INotifyPropertyChanged
{
    private bool _displayRaw;
    public bool DisplayRaw
    {
        get { return _displayRaw; }
        set 
        {
            _displayRaw = value;
            OnPropertyChanged(new PropertyChangedEventArgs("DisplayRaw"));
        }
    }

    private bool _enableFit;
    public bool EnableFit
    {
        get { return _enableFit; }
        set
        {
            _enableFit = value;
            OnPropertyChanged(new PropertyChangedEventArgs("EnableFit"));
        }
    }

    public ZoomGraphControlValues()
    {}

    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, e);
    }
}

这里是依赖属性:

public ZoomGraphControlValues ControlValues
    {
        get { return (ZoomGraphControlValues)GetValue(ControlValuesProperty); }
        set { SetValue(ControlValuesProperty, value); }
    }

    public static readonly DependencyProperty ControlValuesProperty =
        DependencyProperty.Register("ControlValues", typeof(ZoomGraphControlValues), typeof(ZoomGraphControls), new PropertyMetadata(null, OnControlValuesPropertyChanged));


    private static void OnControlValuesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var myObj = d as ZoomGraphControls;
        myObj.OnControlValuesPropertyChanged(e);
    }

    private void OnControlValuesPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        if (ControlValues != null)
        {
            IniValues();
        }
    }

然后我有显示用户控件。此控件还实现了与其他控件相同类型的依赖属性,并且我希望此控件成为绑定的目标,以便当我更改参数控件中的值时,此控件会反映更改。

这里是这个控件的依赖属性:

    public ZoomGraphControlValues ZoomGraphControlValues
        {
            get { return (ZoomGraphControlValues)GetValue(ZoomGraphControlValuesProperty); }
            set { SetValue(ZoomGraphControlValuesProperty, value); }
        }

        public static readonly DependencyProperty ZoomGraphControlValuesProperty =
            DependencyProperty.Register("ZoomGraphControlValues", typeof(ZoomGraphControlValues), typeof(zoomGraph), new PropertyMetadata(null, OnZoomGraphControlValuesPropertyChanged));


        private static void OnZoomGraphControlValuesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var myObj = d as zoomGraph;
            myObj.OnZoomGraphControlValuesPropertyChanged(e);
        }

        private void OnZoomGraphControlValuesPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (ZoomGraphControlValues != null)
            {

  // update the control with the new parameters
  ShowRawData(ZoomGraphControlValues.DisplayRaw);
                SetChartBehabiour();
            }
        }

Parameters 控件从应用程序周期开始就被初始化。显示控件是根据用户请求创建到选项卡中的,因此我必须以编程方式创建控件,从而进行绑定:

//create the tab and wire tab events
//…

//create a display control

var graph = new zoomGraph();

// initialize the parameters class

var zgcv = new ZoomGraphControlValues
{
  DisplayRaw = true,
  ChartBehaviour = ChartBehaviour.Zoom
};

//assign the parameters class to the parameters user control dependency property

ZoomGraphControlsControl.ControlValues = zgcv;

//create the binding of the parameter control to the display control by linking their respective dependency properties

var zoomGraphControlValuesBinding = new Binding();
zoomGraphControlValuesBinding.Source = ZoomGraphControlsControl;
zoomGraphControlValuesBinding.Path = new PropertyPath("ControlValues");
zoomGraphControlValuesBinding.Mode = BindingMode.TwoWay;
zoomGraphControlValuesBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
zoomGraphControlValuesBinding.NotifyOnSourceUpdated = true;
zoomGraphControlValuesBinding.NotifyOnTargetUpdated = true;

graph.SetBinding(zoomGraph.ZoomGraphControlValuesProperty, zoomGraphControlValuesBinding);

//…
// add the user control to a tab

当我更改参数控件中的参数时,我可以看到它尝试触发 OnPropertyChanged 事件,但它始终为空。正因为如此,我觉得我缺少一些东西。

【问题讨论】:

    标签: wpf data-binding dependency-properties inotifypropertychanged


    【解决方案1】:

    您将绑定模式设置为“OneWay”,这意味着当视图中的值更改时,视图模型将永远不会更新。将绑定模式更改为“TwoWay”,然后重试。

    此外,请检查您是更改“DisplayControlValues”的完整实例还是仅更改该类的属性,因为您的绑定仅在整个实例更改时触发,而不是其属性。

    除此之外,请记住,您可以使用 Binding.ElementName 属性绑定两个不同控件的属性,这将使您无需创建视图模型,除非您需要的代码中有任何内容当这些值改变时做。

    如果您发布更多代码和 XAML,将更容易找到解决问题的最合适方法。

    【讨论】:

    • 感谢您的回答 Murven,我在帖子中添加了更多详细信息。我还尝试了双向绑定,结果相同。您提到我的绑定是为整个实例更改设置的,我在哪里控制如何仅针对属性更改,也许这是我的问题。
    • 绑定只监控它所绑定的实例上的变化,而不是该实例内的属性,这意味着您与 ZoomGraphControlValues 的绑定不会监控 ZoomGraphControlValues.Source 上的任何变化。您需要为该属性创建一个特定绑定以使其监视更改。您可以通过将 ControlValues 属性设置为 null 来测试此理论,然后在更改其属性之一后将其设置为您正在使用的实例,这应该会强制触发绑定并让您确定原因。
    • 感谢您的建议 Murven,使用 null 可以帮助我强制检查并且它有效。你所有的建议都很棒,帮助我理解了我的问题。我想尝试按照您的建议直接绑定两个用户控件的控件,但在我的场景中(以编程方式创建绑定)我在成功时遇到问题,但这与我原来的问题无关,所以我将开始一个新问题.
    猜你喜欢
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2010-11-23
    • 2018-08-08
    • 1970-01-01
    相关资源
    最近更新 更多