Fra*_*Liu 10 c# wpf itemscontrol observablecollection mvvm
问题:
ItemsControl(或从中派生的控件ItemsControl).ItemsControl.ItemsSource属性绑定到ObservableCollectionViewModel中的a.ObservableCollection.ObservableCollection.背景:
这似乎是许多WPF开发人员遇到的常见问题.有人问过几次:
ObservableCollection没有注意到它中的Item何时发生变化(即使使用INotifyPropertyChanged)
ObservableCollection和Item PropertyChanged
我的实施:
当Item更改时,我尝试在Notify ObservableCollection中实现接受的解决方案.基本思想是PropertyChanged在MainWindowViewModel中为每个项目连接一个处理程序ObservableCollection.更改项目的属性时,将调用事件处理程序,并以某种方式更新视图.
我无法让实现工作.这是我的实施.
的ViewModels:
class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName = "")
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Run Code Online (Sandbox Code Playgroud)
项目视图模型:
class EmployeeViewModel : ViewModelBase
{
private int _age;
private string _name;
public int Age
{
get { return _age; }
set
{
_age = value;
RaisePropertyChanged("Age");
}
}
public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
public override string ToString()
{
return string.Format("{0} is {1} years old", Name, Age);
}
}
Run Code Online (Sandbox Code Playgroud)
主窗口ViewModel:
class MainWindowViewModel : ViewModelBase
{
private ObservableCollection<EmployeeViewModel> _collection;
public MainWindowViewModel()
{
_collection = new ObservableCollection<EmployeeViewModel>();
_collection.CollectionChanged += MyItemsSource_CollectionChanged;
AddEmployeeCommand = new DelegateCommand(() => AddEmployee());
IncrementEmployeeAgeCommand = new DelegateCommand(() => IncrementEmployeeAge());
}
public ObservableCollection<EmployeeViewModel> Employees
{
get { return _collection; }
}
public ICommand AddEmployeeCommand { get; set; }
public ICommand IncrementEmployeeAgeCommand { get; set; }
public void AddEmployee()
{
_collection.Add(new EmployeeViewModel()
{
Age = 1,
Name = "Random Joe",
});
}
public void IncrementEmployeeAge()
{
foreach (var item in _collection)
{
item.Age++;
}
}
private void MyItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach (EmployeeViewModel item in e.NewItems)
item.PropertyChanged += ItemPropertyChanged;
if (e.OldItems != null)
foreach (EmployeeViewModel item in e.OldItems)
item.PropertyChanged -= ItemPropertyChanged;
}
private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
RaisePropertyChanged("Employees");
}
}
Run Code Online (Sandbox Code Playgroud)
视图:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
xmlns:d="clr-namespace:Iress.IosPlus.DynamicOE.Controls"
Title="MainWindow" Height="350" Width="350">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.3*"></ColumnDefinition>
<ColumnDefinition Width="0.7*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<Button Command="{Binding AddEmployeeCommand}">Add Employee</Button>
<Button Command="{Binding IncrementEmployeeAgeCommand}">Increment Employee Age</Button>
</StackPanel>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="0.1*"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Path=Employees[0]}"></TextBlock>
<ItemsControl Grid.Row="1" ItemsSource="{Binding Path=Employees}" BorderBrush="Red" BorderThickness="1"></ItemsControl>
</Grid>
</Grid>
Run Code Online (Sandbox Code Playgroud)
我的结果:
为了验证我的实现,我创建了一个这样的视图.将TextBlock.Text被绑定到集合中的第一项.它ItemsControl与集合本身绑定在一起.
EmployeeViewModel集合中的对象,无论是TextBlock和ItemsControl按预期进行更新.ItemsControl使用另一个条目进行更新.大!Age每个项目的属性增加1. PropertyChanged事件被引发.该ItemPropertyChanged事件处理函数.该Textblock预期被更新.但是,ItemsControl没有更新.我认为,当项目更改ItemsControl时,Employee.Age根据Notify ObservableCollection中的答案更改 时,应该更新.

Azz*_*ziz 11
我找到了使用Snoop调试XAML 的答案.
问题是您正在尝试绑定到ToString()方法,并且不会引发PropertyChanged事件.如果查看XAML绑定,您会注意到ObservableCollection实际上正在发生变化.

现在查看每个项目控件及其在"Text"属性中的文本绑定.没有,它只是文字.

要解决此问题,只需添加一个ItemsControl ItemTemplate,其中包含一个DataTemplate,其中包含您要显示的元素.
<ItemsControl Grid.Row="1" ItemsSource="{Binding Path=Employees, UpdateSourceTrigger=PropertyChanged}" BorderBrush="Red" BorderThickness="1" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat=" {0} is {1} years old">
<Binding Path="Name"/>
<Binding Path="Age"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
我们现在对绑定有了一个绿灯.正在调用RaisePropertyChanged.

当当!

| 归档时间: |
|
| 查看次数: |
13583 次 |
| 最近记录: |