ItemsSource 绑定不更新值
ItemsSource binding do not update values
我需要列出项目。我将用户集合绑定到列表框。一切正常,但列表框中的项目不会实时更新。它们根本不会被这个绑定更新。因此,当我从列表中删除任何用户时,即使正确更改了列表框的来源,列表框也不会更新。
源位于路径 DataViewModel.Instance.AllUsers 的数据视图模型中;每当我将新项目添加到此列表或删除一个项目时,布局都不会更新。其他绑定工作良好。我尝试更新列表框布局,引发源更新事件,adding/removing 项目的其他方式,但没有任何效果。
我尝试调试绑定,但绑定太多,无法找到错误。
提前感谢您提供任何有用的建议。
列表框:
<ListBox x:Name="ListboxUsers" ItemsSource="{Binding Path=AllUsers, Mode=OneWay}" Grid.Column="1" Margin="0" Grid.Row="5" Background="DimGray" BorderThickness="0" Visibility="Hidden" SelectionChanged="ListboxUsers_SelectionChanged"/>
代码隐藏:
CatalogueGrid.DataContext = DataViewModel.Instance; //whole view model added as datacontext
DataViewModel 类:
public class DataViewModel : INotifyPropertyChanged
{
private static DataViewModel _dataViewModel;
private Collection<UserModel> allUsers;
public Collection<UserModel> AllUsers
{
get
{
return allUsers;
}
set
{
allUsers = value;
NotifyPropertyChanged("AllUsers");
}
}
private DataViewModel()
{
AllUsers = new Collection<UserModel>();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(info));
}
}
.
.
.
}
要将对集合的更改传播到 UI,集合 class 需要实施 INotifyCollectionChanged
。
已经实现的一个非常有用的class是ObservableCollection<T>
(MSDN)。使用它代替 Collection<T>
.
如果 Collection
实现了 INotifyCollectionChanged
接口,则使用 ObservableColLection
代替:
private ObservableCollection<UserModel> allUsers;
public ObservableCollection<UserModel> AllUsers
{
get
{
return allUsers;
}
set
{
allUsers = value;
NotifyPropertyChanged("AllUsers");
}
}
您已将您的列表框绑定到一个 Collection<T>
- 这只是一个列表,它不会发出任何通知来告知其内容已更改的绑定属性。因此,您的列表框不可能知道集合何时更改。
相反,您可以使用 ObservableCollection<T>
class (or, more precisely, any collection that also implements INotifyCollectionChanged
),更改将自动传播到列表框。
请注意,您的 属性 没有 可以键入 ObservableCollection<T>
,您也可以只声明 public 属性 as IEnumerable<T>
or IList<T>
; the binding will find out on its own whether the returned class also implements INotifyCollectionChanged
. Like this, you are free to replace your actual underlying collection class later on, for example with a ReadOnlyObservableCollection<T>
,如果你想禁止来自外部的更改。
说到这里,请注意您的代码:您已经为 AllUsers
属性 提供了 setter。这可能会导致意外的后果,因为您打开了一些其他代码将 属性 设置为 null
的可能性,这(取决于您的代码的其余部分)可能会导致异常。除非你真的想允许分配新值,否则对于 ItemsSource
属性 绑定,只读 属性 就足够了,只要返回的集合对象实现 INotifyCollectionChanged
.
我需要列出项目。我将用户集合绑定到列表框。一切正常,但列表框中的项目不会实时更新。它们根本不会被这个绑定更新。因此,当我从列表中删除任何用户时,即使正确更改了列表框的来源,列表框也不会更新。
源位于路径 DataViewModel.Instance.AllUsers 的数据视图模型中;每当我将新项目添加到此列表或删除一个项目时,布局都不会更新。其他绑定工作良好。我尝试更新列表框布局,引发源更新事件,adding/removing 项目的其他方式,但没有任何效果。
我尝试调试绑定,但绑定太多,无法找到错误。
提前感谢您提供任何有用的建议。
列表框:
<ListBox x:Name="ListboxUsers" ItemsSource="{Binding Path=AllUsers, Mode=OneWay}" Grid.Column="1" Margin="0" Grid.Row="5" Background="DimGray" BorderThickness="0" Visibility="Hidden" SelectionChanged="ListboxUsers_SelectionChanged"/>
代码隐藏:
CatalogueGrid.DataContext = DataViewModel.Instance; //whole view model added as datacontext
DataViewModel 类:
public class DataViewModel : INotifyPropertyChanged
{
private static DataViewModel _dataViewModel;
private Collection<UserModel> allUsers;
public Collection<UserModel> AllUsers
{
get
{
return allUsers;
}
set
{
allUsers = value;
NotifyPropertyChanged("AllUsers");
}
}
private DataViewModel()
{
AllUsers = new Collection<UserModel>();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(info));
}
}
.
.
.
}
要将对集合的更改传播到 UI,集合 class 需要实施 INotifyCollectionChanged
。
已经实现的一个非常有用的class是ObservableCollection<T>
(MSDN)。使用它代替 Collection<T>
.
如果 Collection
实现了 INotifyCollectionChanged
接口,则使用 ObservableColLection
代替:
private ObservableCollection<UserModel> allUsers;
public ObservableCollection<UserModel> AllUsers
{
get
{
return allUsers;
}
set
{
allUsers = value;
NotifyPropertyChanged("AllUsers");
}
}
您已将您的列表框绑定到一个 Collection<T>
- 这只是一个列表,它不会发出任何通知来告知其内容已更改的绑定属性。因此,您的列表框不可能知道集合何时更改。
相反,您可以使用 ObservableCollection<T>
class (or, more precisely, any collection that also implements INotifyCollectionChanged
),更改将自动传播到列表框。
请注意,您的 属性 没有 可以键入 ObservableCollection<T>
,您也可以只声明 public 属性 as IEnumerable<T>
or IList<T>
; the binding will find out on its own whether the returned class also implements INotifyCollectionChanged
. Like this, you are free to replace your actual underlying collection class later on, for example with a ReadOnlyObservableCollection<T>
,如果你想禁止来自外部的更改。
说到这里,请注意您的代码:您已经为 AllUsers
属性 提供了 setter。这可能会导致意外的后果,因为您打开了一些其他代码将 属性 设置为 null
的可能性,这(取决于您的代码的其余部分)可能会导致异常。除非你真的想允许分配新值,否则对于 ItemsSource
属性 绑定,只读 属性 就足够了,只要返回的集合对象实现 INotifyCollectionChanged
.