2011-10-11 74 views
3

我有一个组合框在我MainWindow.xaml文件,像这样的工作:INotifyPropertyChanged的不使用WPF数据绑定

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

我分配使用this.datacontext = this在代码隐藏在DataContext。

我创建了作为MainWindow属性进行访问,并且是实现INotifyPropertyChanged并包含MaterialDropDownValues作为属性类ViewProperties

我甚至将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并使该属性成为可观察集合。

+2

请注意,如果您只是从列表中添加/删除数据,则不应重新绑定整个集合。你应该这样做:'materialDropDownValues.Remove(value);'。 –

+0

在过去,当我遇到这个问题时,它有时是由其他(代码隐藏)代码直接编程设置ItemsSource(从而终止绑定)导致的。 – bigtlb

+0

注意:整个列表可以立即更改,不仅仅是需要添加或删除的单个项目。 – Seth

回答

0

当我遇到这样的事情时,我所做的第一件事就是玩弄绑定模式。例如:

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

有时候会让你失望。另一件事我会确定的是,如果您在初始加载后实例化新的ViewProperties对象,则通知您发生更改。如果不这样做,那么XAML将引用该对象的过时版本,而您的代码隐藏/视图模型在另一个版本上运行。

+0

我怀疑这与绑定的方向有什么关系 - “ItemsSource”将默认为“OneWay”,这至少意味着将显示项目。作为一个方面说明,如果您在运行时查看Visual Studio中的调试窗口,它通常会向您显示(良性)错误消息,如果出于某种原因无法解析“绑定”,那么这是一个相当不错的第一诊断步骤 –

0

编辑回应评论

无的下方解决了这个问题,但留下作为参考。


原来的答案

的问题是,你有没有指定的DataContext对你的看法,这是在WPF查找Binding值默认。

只要你ViewProperties财产上MainWindow是公开的,你可以简单地改变你的绑定:

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

这将导致WPF找上Window首次出现的属性值,它找到的组合框上面视觉树。

或者,你可以在Window.DataContext属性正好被设置为你的ViewProperties实例,并更改绑定到以下几点:

ItemsSource="{Binding MaterialDropDownValues}" 

任何一项都将工作,但我会建议使用后者,因为它更接近到WPF/XAML应用程序中通常首选的MVVM模式。

+0

我确实指定了datacontext作为代码中的MainWindow(按照答案)。但是,您说我没有为该绑定指定正确的数据上下文? – Seth

+0

啊,是的,你确实提到过。我从来没有见过过设置'this.DataContext = this'的例子,所以我不能说它是否应该有效。无论如何,我描述的任何一种方法都应该解决这个问题。 –

+0

刚刚做了一个快速测试,'this.DataContext = this'似乎对我来说很好...... –

0

,如果你改变你的XAML来

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

不过你应该只是实例化您的收藏一次,并只使用删除,增加和明确的,当你使用OberservableCollection会发生什么。

1

解决方案1:

不要重新this.materialDropDownValues试图为所有新项目做

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

。如果这不工作然后尝试解决2 ...

解决方案2:

按我的经验,我认为基本类型的ObservableCollectionintstringbooldouble等的房产不刷新如果未指定ItemsControl.ItemTemplate,则更改通知。

<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中的物品的容器通过简单地复制item.ToString创造了它不可观察的项目容器的原始数据()。在上面的代码中,{Binding}应更新整个项目源更改时的数据更改。

让我知道这是否工作。

+0

刚去度假,但当我回来时,我会在这两个解决方案中去。 – Seth