刷新 itemscontrol wpf 中的绑定
refresh bindings in itemscontrol wpf
我有一个简单的 itemscontrol 绑定到条目对象列表。该按钮更新列表中每个项目的 LastUpdated。如何引发 属性 changed 事件,以便在 ItemsControl 中更新 LastUpdated 字段。我简化了我的例子只是为了弄清楚绑定问题。我的真实示例使用 PRISM 和第三方控件。
C#代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Input;
namespace TestItemsControl
{
public class Entry
{
public string Name { get; set; }
public DateTime LastUpdated { get; set; }
}
}
namespace TestItemsControl
{
public class TestViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public List<Entry> Entries { get; set; }
public ICommand UpdateCmd { get; set; }
public TestViewModel()
{
this.Entries = new List<Entry>();
this.Entries.Add(new Entry{ Name = "1", LastUpdated = DateTime.Now });
this.Entries.Add(new Entry { Name = "2", LastUpdated = DateTime.Now });
this.Entries.Add(new Entry { Name = "3", LastUpdated = DateTime.Now });
}
public void Refresh()
{
if (this.PropertyChanged!= null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Entries"));
}
}
}
}
XAML:
<Application x:Class="TestItemsControl.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestItemsControl"
StartupUri="MainWindow.xaml">
<Application.Resources>
<local:TestViewModel x:Key="viewModel"/>
</Application.Resources>
</Application>
<Window x:Class="TestItemsControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestItemsControl"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" DataContext="{StaticResource viewModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ItemsControl Grid.Row="0" ItemsSource="{Binding Entries}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding LastUpdated}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Grid.Row="1" Content="Update" Click="Button_Click"/>
</Grid>
</Window>
然后你必须重写你的 Entry
class
public class Entry: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
DateTime lastUD;
public DateTime LastUpdated
{
get
{
return lastUD;
}
set
{
lastUD = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("LastUpdated"));
}
}
}
此外,将 List<Entry>
更改为 ObservableCollection<Entry>
:
namespace TestItemsControl
{
public class TestViewModel
{
public ObservableCollection<Entry> Entries=new ObservableCollection<Entry>();
public ICommand UpdateCmd { get; set; }
public TestViewModel()
{
this.Entries.Add(new Entry{ Name = "1", LastUpdated = DateTime.Now });
this.Entries.Add(new Entry { Name = "2", LastUpdated = DateTime.Now });
this.Entries.Add(new Entry { Name = "3", LastUpdated = DateTime.Now });
}
}
}
这样就不用调用刷新函数了。
如果没有人订阅该事件,您必须检查是否为 Null
public class Entry : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
DateTime lastUD;
public DateTime LastUpdated
{
get
{
return lastUD;
}
set
{
lastUD = value;
if(PropertyChanged != NULL)
PropertyChanged(this, new PropertyChangedEventArgs("LastUpdated"));
}
}
}
我想你必须在这里选择:
创建这样的方法:
protected void OnPropertyChanged(string)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
然后每当你想更新一个属性你去:
OnPropertyChanged("TheNameOfTheProperty");
或者如果您想更新 class 中的每个属性:
OnPropertyChanged(string.Empty);
如果您不确定 属性 何时更新,我建议您选择后者。
- 你可以,但我建议你不要这样做:实例化一个新列表,添加更新的值,清除原始列表,将原始列表设置为新列表,然后更新 属性 列表名称。
您没有绑定 UpdateCmd 并在任何地方调用 Refresh,除非它在 Click 处理程序中,但您应该使用 MVVM 方法来执行此操作。
在 xaml 中将 Click 事件处理程序更改为命令绑定,就像这样
<Button Grid.Row="1" Content="Update" Command={Binding UpdateCmd}/>
然后在 viewmodel 的构造函数中绑定创建一个新的 RelayCommand 或者 ICommand 实现 class 就像构造函数接受动作委托的地方一样。
this.UpdateCmd = new RelayCommand(this.Update);
此外,您也许应该将刷新更改为更新,以更新条目的时间戳。
public void Update()
{
foreach (var entry in this.Entries)
{
entry.LastUpdated = DateTime.Now;
}
if (this.PropertyChanged!= null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Entries"));
}
}
但是您实际上也应该在您的 Entry 模型上实现 INotifyPropertyChanged 并在 属性 setter 上引发事件,绑定将在不通知应更新整个集合的情况下更新。
我有一个简单的 itemscontrol 绑定到条目对象列表。该按钮更新列表中每个项目的 LastUpdated。如何引发 属性 changed 事件,以便在 ItemsControl 中更新 LastUpdated 字段。我简化了我的例子只是为了弄清楚绑定问题。我的真实示例使用 PRISM 和第三方控件。
C#代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Input;
namespace TestItemsControl
{
public class Entry
{
public string Name { get; set; }
public DateTime LastUpdated { get; set; }
}
}
namespace TestItemsControl
{
public class TestViewModel: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public List<Entry> Entries { get; set; }
public ICommand UpdateCmd { get; set; }
public TestViewModel()
{
this.Entries = new List<Entry>();
this.Entries.Add(new Entry{ Name = "1", LastUpdated = DateTime.Now });
this.Entries.Add(new Entry { Name = "2", LastUpdated = DateTime.Now });
this.Entries.Add(new Entry { Name = "3", LastUpdated = DateTime.Now });
}
public void Refresh()
{
if (this.PropertyChanged!= null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Entries"));
}
}
}
}
XAML:
<Application x:Class="TestItemsControl.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestItemsControl"
StartupUri="MainWindow.xaml">
<Application.Resources>
<local:TestViewModel x:Key="viewModel"/>
</Application.Resources>
</Application>
<Window x:Class="TestItemsControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestItemsControl"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" DataContext="{StaticResource viewModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ItemsControl Grid.Row="0" ItemsSource="{Binding Entries}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding LastUpdated}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Grid.Row="1" Content="Update" Click="Button_Click"/>
</Grid>
</Window>
然后你必须重写你的 Entry
class
public class Entry: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
DateTime lastUD;
public DateTime LastUpdated
{
get
{
return lastUD;
}
set
{
lastUD = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("LastUpdated"));
}
}
}
此外,将 List<Entry>
更改为 ObservableCollection<Entry>
:
namespace TestItemsControl
{
public class TestViewModel
{
public ObservableCollection<Entry> Entries=new ObservableCollection<Entry>();
public ICommand UpdateCmd { get; set; }
public TestViewModel()
{
this.Entries.Add(new Entry{ Name = "1", LastUpdated = DateTime.Now });
this.Entries.Add(new Entry { Name = "2", LastUpdated = DateTime.Now });
this.Entries.Add(new Entry { Name = "3", LastUpdated = DateTime.Now });
}
}
}
这样就不用调用刷新函数了。
如果没有人订阅该事件,您必须检查是否为 Null
public class Entry : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
DateTime lastUD;
public DateTime LastUpdated
{
get
{
return lastUD;
}
set
{
lastUD = value;
if(PropertyChanged != NULL)
PropertyChanged(this, new PropertyChangedEventArgs("LastUpdated"));
}
}
}
我想你必须在这里选择:
创建这样的方法:
protected void OnPropertyChanged(string) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } }
然后每当你想更新一个属性你去:
OnPropertyChanged("TheNameOfTheProperty");
或者如果您想更新 class 中的每个属性:
OnPropertyChanged(string.Empty);
如果您不确定 属性 何时更新,我建议您选择后者。
- 你可以,但我建议你不要这样做:实例化一个新列表,添加更新的值,清除原始列表,将原始列表设置为新列表,然后更新 属性 列表名称。
您没有绑定 UpdateCmd 并在任何地方调用 Refresh,除非它在 Click 处理程序中,但您应该使用 MVVM 方法来执行此操作。
在 xaml 中将 Click 事件处理程序更改为命令绑定,就像这样
<Button Grid.Row="1" Content="Update" Command={Binding UpdateCmd}/>
然后在 viewmodel 的构造函数中绑定创建一个新的 RelayCommand 或者 ICommand 实现 class 就像构造函数接受动作委托的地方一样。
this.UpdateCmd = new RelayCommand(this.Update);
此外,您也许应该将刷新更改为更新,以更新条目的时间戳。
public void Update()
{
foreach (var entry in this.Entries)
{
entry.LastUpdated = DateTime.Now;
}
if (this.PropertyChanged!= null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Entries"));
}
}
但是您实际上也应该在您的 Entry 模型上实现 INotifyPropertyChanged 并在 属性 setter 上引发事件,绑定将在不通知应更新整个集合的情况下更新。