繁体   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