WPF绑定顺序如何确保一个属性先于另一个属性绑定

时间:2020-12-27 20:56:13
<Controls:MyControl Mode="Mode1" Value="{Binding Path=Something}" />

The problem I have is that binding happens before Mode property is being set when I use this control in a data template of a ListView.

我遇到的问题是,当我在ListView的数据模板中使用此控件时,绑定在Mode属性设置之前发生。

How do I make sure that Mode is always set before Value binding?

如何确保模式总是在值绑定之前设置?

2 个解决方案

#1


1  

What you could do is delay the binding, so you can be (almost) sure the mode value is set till then. There's a delay binding property in .net 4.5. Here's an article on how to simulate that in .net 4.0 Delay property on Binding from .Net 4.5 in .Net 4.0

您可以做的是延迟绑定,因此您可以(几乎)确定在此之前设置了模式值。在。net 4.5中有一个延迟绑定属性。这里有一篇关于如何在。net 4.0中模拟从。net 4.5到。net 4.0中的绑定延迟属性的文章

I personally would implement that in a viewModel (MVVM), where this kind of issue is rather simple to resolve. Make two properties Mode and Something. When mode changes it should trigger that the "Something" property was changed also ( via INotifyPropertyChanged Interface).

我个人会在viewModel (MVVM)中实现这一点,在这种情况下,这类问题很容易解决。创建两个属性模式。当模式改变时,它应该会触发“Something”属性也被改变(通过INotifyPropertyChanged接口)。

class MyViewModel : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
      if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    private string _mode;

    public string Mode
    {
      get { return _mode; }
      set
      {
        _mode = value;
        OnPropertyChanged("Mode");

        // OnPropertyChanged("Something");
        // or build up via a method:
        // Something = DetermineFromMode(Mode);
      }
    }

    private string _something;

    public string Something
    {
      get { return _something;  }
      set
      {
        _something = value;
        OnPropertyChanged("Something");
      }
    }
  }

#2


1  

Have you tried raising the property changed event for your property "Something" when Mode of your control get set? You can get the property "Something" in you control like this -

当你的控件的模式被设置时,你是否尝试过为你的属性“某物”增加属性更改事件?你可以得到你控制的属性“某物”,像这样

Binding binding = BindingOperations.GetBindingExpression(this, this.Value).ParentBindingBase;
String propertyToRefresh = binding.Path.Path;

(this.DataContext as ViewModel).OnPropertyChange(propertyToRefresh);

I am assuming that the DataContext of your Control is your ViewModel's instance which implements INotifyPropertyChangedInterface.

我假设您的控件的DataContext是实现INotifyPropertyChangedInterface的ViewModel实例。

In case your Viemodel class OnPropertyChange method is not public or you don't have reference to your ViewModel class in your control. You can simply call the UpdateTarget() on your BindingExpression like this (as suggested by Thomas Levesque) -

如果您的Viemodel类OnPropertyChange方法不是公共的,或者您没有在控件中引用您的ViewModel类。您可以简单地调用BindingExpression上的UpdateTarget()(如Thomas Levesque所建议的)-

BindingExpression binding = BindingOperations.GetBindingExpression(this, this.Value);
binding.UpdateTarget();

#1


1  

What you could do is delay the binding, so you can be (almost) sure the mode value is set till then. There's a delay binding property in .net 4.5. Here's an article on how to simulate that in .net 4.0 Delay property on Binding from .Net 4.5 in .Net 4.0

您可以做的是延迟绑定,因此您可以(几乎)确定在此之前设置了模式值。在。net 4.5中有一个延迟绑定属性。这里有一篇关于如何在。net 4.0中模拟从。net 4.5到。net 4.0中的绑定延迟属性的文章

I personally would implement that in a viewModel (MVVM), where this kind of issue is rather simple to resolve. Make two properties Mode and Something. When mode changes it should trigger that the "Something" property was changed also ( via INotifyPropertyChanged Interface).

我个人会在viewModel (MVVM)中实现这一点,在这种情况下,这类问题很容易解决。创建两个属性模式。当模式改变时,它应该会触发“Something”属性也被改变(通过INotifyPropertyChanged接口)。

class MyViewModel : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
      if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    private string _mode;

    public string Mode
    {
      get { return _mode; }
      set
      {
        _mode = value;
        OnPropertyChanged("Mode");

        // OnPropertyChanged("Something");
        // or build up via a method:
        // Something = DetermineFromMode(Mode);
      }
    }

    private string _something;

    public string Something
    {
      get { return _something;  }
      set
      {
        _something = value;
        OnPropertyChanged("Something");
      }
    }
  }

#2


1  

Have you tried raising the property changed event for your property "Something" when Mode of your control get set? You can get the property "Something" in you control like this -

当你的控件的模式被设置时,你是否尝试过为你的属性“某物”增加属性更改事件?你可以得到你控制的属性“某物”,像这样

Binding binding = BindingOperations.GetBindingExpression(this, this.Value).ParentBindingBase;
String propertyToRefresh = binding.Path.Path;

(this.DataContext as ViewModel).OnPropertyChange(propertyToRefresh);

I am assuming that the DataContext of your Control is your ViewModel's instance which implements INotifyPropertyChangedInterface.

我假设您的控件的DataContext是实现INotifyPropertyChangedInterface的ViewModel实例。

In case your Viemodel class OnPropertyChange method is not public or you don't have reference to your ViewModel class in your control. You can simply call the UpdateTarget() on your BindingExpression like this (as suggested by Thomas Levesque) -

如果您的Viemodel类OnPropertyChange方法不是公共的,或者您没有在控件中引用您的ViewModel类。您可以简单地调用BindingExpression上的UpdateTarget()(如Thomas Levesque所建议的)-

BindingExpression binding = BindingOperations.GetBindingExpression(this, this.Value);
binding.UpdateTarget();