簡體   English   中英

INotifyPropertyChanged無法使用WPF數據綁定

[英]INotifyPropertyChanged not working with WPF data binding

我的MainWindow.xaml文件中有一個組合框,如下所示:

<ComboBox Name="material1ComboBox" 
          HorizontalAlignment="Center" 
          MinWidth="100" 
          ItemsSource="{Binding ViewProperties.MaterialDropDownValues}" 
          SelectedValue="{Binding ViewProperties.Material1SelectedValue}"
          SelectionChanged="Material1ComboBoxSelectionChanged">
 </ComboBox>

我使用this.datacontext = this在codebehind中分配了datacontext。

我創建了一個ViewProperties ,它作為MainWindow的屬性進行訪問,是一個實現INotifyPropertyChanged並包含MaterialDropDownValues作為屬性的類。

我甚至將MaterialDropDownValues更改為ObservableCollection

問題是數據綁定在初始化時起作用,但是如果更改了MaterialDropDownValues屬性,則不會更新組合框值。

我在ViewProperties類中有以下內容:

    public ObservableCollection<string> MaterialDropDownValues 
    { 
        get { return this.materialDropDownValues; }
        set 
        { 
            this.materialDropDownValues = value;

            OnPropertyChanged("MaterialDropDownValues");
        } 
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

任何想法為什么這不起作用? 我能找到的所有其他答案都建議實現INotifyPropertyChanged並使該屬性成為一個observablecollection。

解決方案1:

不要重新創建this.materialDropDownValues嘗試做

 this.materialDropDownValues.Clear();
 foreach(var mystring in myStrings) 
       this.materialDropDownValues.Add(mystring);

對於所有新項目。 如果這不起作用,那么嘗試解決方案2 ......

解決方案2:

根據我的經驗,我認為如果未指定ItemsControl.ItemTemplate則不會在Property Change通知上刷新像intstringbooldouble等原始類型的ObservableCollection

   <ComboBox Name="material1ComboBox"
             HorizontalAlignment="Center"
             MinWidth="100"
             ItemsSource="{Binding ViewProperties.MaterialDropDownValues}"
             SelectedValue="{Binding ViewProperties.Material1SelectedValue}"
             SelectionChanged="Material1ComboBoxSelectionChanged">
         <ComboBox.ItemTemplate>
             <DataTemplate DataType="{x:Type System:String}">
                 <TextBlock Text="{Binding}" />
             </DataTemplate> 
         </ComboBox.ItemTemplate>
    </ComboBox>

這是因為itemscontrol的items容器只需復制item.ToString()就可以在其中為原始數據創建不可觀察的項容器。 在上面的代碼中, {Binding}應該在更改整個項目源時更新數據更改。

讓我知道這個是否奏效。

當我碰到這樣的事情時,我做的第一件事就是玩弄綁定模式。 就像是:

 ItemsSource="{Binding Path=ViewProperties.MaterialDropDownValues, Mode=TwoWay}"

這有時會讓你失望。 我要確定的另一件事是,如果您在初始加載后實例化新的ViewProperties對象,則通知更改。 如果不這樣做,XAML將引用該對象的過時版本,而您的代碼隱藏/視圖模型在另一個版本上運行。

編輯以回應評論

以下都沒有解決問題,但留作參考。


原始答案

問題是您沒有為視圖指定DataContext ,這是WPF默認查找Binding值的地方。

如果MainWindow上的ViewProperties屬性是公共的,您只需將綁定更改為:

ItemsSource="{Binding ViewProperties.MaterialDropDownValues, 
    RelativeSource={RelativeSource FindAncestor, AncestorType=Window}"

這會導致WPF在可視樹中的組合框上方找到的Window的第一個出現時查找屬性值。

或者,您可以將Window.DataContext屬性設置為Window.DataContext實例, ViewProperties綁定更改為以下內容:

ItemsSource="{Binding MaterialDropDownValues}"

這些中的任何一個都可以工作,但我建議使用后者,因為它更接近MVF模式,這在WPF / XAML應用程序中通常是首選的。

如果你改變你的xaml會發生什么

<ComboBox Name="material1ComboBox" 
      HorizontalAlignment="Center" 
      MinWidth="100" 
      DataContext="{Binding ViewProperties}"
      ItemsSource="{Binding MaterialDropDownValues}" 
      SelectedValue="{Binding Material1SelectedValue}"
      SelectionChanged="Material1ComboBoxSelectionChanged">
</ComboBox>

盡管如此,您只需要實例化您的集合一次,並在使用OberservableCollection時使用remove,add和clear。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM