更改集合时 WPF 组合框不更新
Posted
技术标签:
【中文标题】更改集合时 WPF 组合框不更新【英文标题】:WPF Combobox not updating when collection is changed 【发布时间】:2013-11-03 04:39:43 【问题描述】:我是 WPF 新手。
我正在尝试将字符串集合绑定到组合框。
public ObservableCollection<string> ListString get; set;
Binding和datacontext设置如下
<Window
x:Class="Assignment2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:validators="clr-namespace:Assignment2"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="Binding RelativeSource=RelativeSource Self, Path=.">
<Grid>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="109,103,0,0" Name="StringComboBox" VerticalAlignment="Top" Width="120" SelectionChanged="StringComboBox_SelectionChanged">
<ComboBox.ItemsSource>
<Binding Path="ListString" BindsDirectlyToSource="True" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"></Binding>
</ComboBox.ItemsSource>
</ComboBox>
我知道这是因为收藏正在更新。如果我写
public MainWindow()
InputString = "";
ListString = new ObservableCollection<string>();
ListString.Add("AAA");
ListString.Add("BBB");
ListString.Add("CCC");
InitializeComponent();
它确实有效,但如果我将InitializeComponent()
移动到第一行上方,如下所示,它不起作用。
public MainWindow()
InitializeComponent();
InputString = "";
ListString = new ObservableCollection<string>();
ListString.Add("AAA");
ListString.Add("BBB");
ListString.Add("CCC");
我该怎么办??
【问题讨论】:
一个有效,另一个无效。我会选择可行的选项。 @Blam 我试图概括这个问题以解决我的另一个问题,其中列表来自 WCF 服务。您仍然建议使用可行的选项吗?? 【参考方案1】:如果您将代码更改为会发生什么
<Window
x:Class="Assignment2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:validators="clr-namespace:Assignment2"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="109,103,0,0" Name="StringComboBox" VerticalAlignment="Top" Width="120" SelectionChanged="StringComboBox_SelectionChanged"
ItemsSource="Binding ListString, Mode=OneWay"/>
cs.
public MainWindow()
InitializeComponent();
InputString = "";
ListString = new ObservableCollection<string>();
ListString.Add("AAA");
ListString.Add("BBB");
ListString.Add("CCC");
this.DataContext=this;
顺便说一句:使用 mode=twoway 设置 ItemsSource 对我来说毫无意义。您的组合框永远不会为您的视图模型“创建新的项目源”。
编辑: 我认为您的第一个解决方案之所以有效,是因为在 xaml 中设置了 DataContext。我假设调用 InitializeComponent(); 时执行 DataContext="Binding RelativeSource=RelativeSource Self, Path=."并且因为您的 ListString 属性只是一个自动属性并且没有实现 INotifyPropertyChanged - 您的主窗口视图不会收到通知您的 ctor 创建了一个新的 ListString 属性。
public ObservableCollection<string> ListString getreturn _list;; set_list=value; OnPropertyChanged("ListString");
应该使用您的两种方法,但您必须为您的 MainWindow 类实现 INotifyPropertyChanged。
【讨论】:
我知道这是因为,当 InitializeComponent 被调用时,它会将该控件绑定到该特定对象引用,并且当引用本身发生更改时,它就不起作用了。 如果你想设置 liststring=new OberservableCollection您可以在后面的代码中设置组合框的项目源,或者在填充列表后再次设置数据上下文,或者您可以使用 inotifychanged 来引发属性更改。
public MainWindow()
InitializeComponent();
InputString = "";
ListString = new ObservableCollection<string>();
ListString.Add("AAA");
ListString.Add("BBB");
ListString.Add("CCC");
StringComboBox.ItemsSource = ListString;
【讨论】:
你确定你添加了 StringComboBox.ItemsSource = ListString;在你的代码中。它应该工作。我已经测试了我的结果和它的工作原理。 对不起,它正在工作,但你不认为我应该通过 XAML 进行绑定【参考方案3】:解决了这个问题。实现 INotifyPropertyChanged 如下
public partial class MainWindow : Window, INotifyPropertyChanged
修改访问器如下
private ObservableCollection<string> listString;
public ObservableCollection<string> ListString
get
return listString;
set
listString = value;
NotifyPropertyChanged("ListString"); // method implemented below
并添加了以下事件和方法来引发事件
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string name)
if (PropertyChanged != null)
PropertyChanged(this,new PropertyChangedEventArgs(name));
它有效 B)
【讨论】:
【参考方案4】:在我看来,问题是“更新”ListString
。使其成为属性(选定的答案)是解决此问题的一种方法。或者内联实例化,或者将它放在InitializeComponent
之前,我相信可以。
如果预计会经常更新,将ObservableCollection
封装在管理器类中可能会有所帮助。在使用这种设置解决我自己的问题后,我发现了这个问题。我通过实现INotifyCollectionChanged
并像这样转发事件来让它工作
/// <summary>
/// Maintains an observable (i.e. good for binding) collection of resources that can be indexed by name or alias
/// </summary>
/// <typeparam name="RT">Resource Type: the type of resource associated with this collection</typeparam>
public class ResourceCollection<RT> : IEnumerable, INotifyCollectionChanged
where RT : class, IResource, new()
public event NotifyCollectionChangedEventHandler CollectionChanged
add Ports.CollectionChanged += value;
remove Ports.CollectionChanged -= value;
public IEnumerator GetEnumerator() return Ports.GetEnumerator();
private ObservableCollection<RT> Ports get; set;
private Dictionary<string, RT> ByAlias get; set;
private Dictionary<string, RT> ByName get; set;
【讨论】:
以上是关于更改集合时 WPF 组合框不更新的主要内容,如果未能解决你的问题,请参考以下文章
在 MVVM 中的 Datagrid 中绑定 WPF 组合框不保存更改
在使用ItemContainerGenerator进行自定义时,WPF ComboBox在第二次打开之前不会更新项目