UI 使用 SetProperty 时不更新添加的项目
UI not updating added item when using SetProperty
我的主窗口上有一个列表框,其中包含以下 XAML
<Window x:Class="MVVMExample.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:MVVMExample"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="241" Margin="24,48,0,0" VerticalAlignment="Top" Width="150" ItemsSource="{Binding Items}"/>
<Label x:Name="label" Content="Items" HorizontalAlignment="Left" Margin="24,17,0,0" VerticalAlignment="Top"/>
<Button x:Name="button" Content="Add Item" HorizontalAlignment="Left" Margin="194,140,0,0" VerticalAlignment="Top" Width="75" Command="{Binding AddItemCommand}"/>
</Grid>
</Window>
我有我的 MainWindowViewModel
using Prism.Commands;
using Prism.Mvvm;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
namespace MVVMExample
{
public class MainWindowViewModel : BindableBase
{
public ICommand AddItemCommand { get; set; }
private List<string> items;
public List<string> Items
{
get { return items; }
set { SetProperty(ref items, value); }
}
public MainWindowViewModel()
{
Items = new List<string>();
Items.Add("Item 1");
AddItemCommand = new DelegateCommand(ExecuteAddItem);
}
private void ExecuteAddItem()
{
Items.Add("Item 2");
}
}
}
据我了解,每当 属性 更改时,SetProperty 方法都会引发 INotifyPropertyChanged 事件。
每当我 运行 这个程序时,我都可以看到 MainWindow 上的列表框确实有项目 "Item 1" 但是当我按下添加项目按钮时,项目 "Item 2" 没有得到添加到 UI 尽管它确实被添加到项目列表中。
我知道如果我使用 ObservableCollection 而不是 List,我可以将 "Item 2" 添加到 ListBox。但是,如果我使用的是 SetProperty 方法,为什么使用 List 不起作用?
我是不是理解错了什么?
当您将新列表分配给 属性 时,您为 Items
发出的唯一通知是在 setter 中。此代码不会将新的 List<string>
实例分配给 Items
。它为 Items
调用 getter 并向列表中添加一个字符串。不会引发任何通知事件,因为您永远不会执行任何引发通知事件的代码。
Items.Add("Item 2");
这是您的 get
区块:
get { return items; }
它不会引发任何事件。无论如何,它在 List<String>.Add()
之前被调用。它怎么知道您打算做的下一件事是向列表中添加一个项目?也许你只是列举一下。如果它知道,在您添加项目之前引发事件有什么用?
List<String>.Add()
也不会引发任何事件。
如果您希望 UI 在您向集合中添加项目时得到通知,请使用 ObservableCollection<String>
。这就是 ObservableCollection<T>
存在的原因:所以有一个集合会在您添加或删除项目时通知 UI。如果仅仅有引发事件的代码的模糊接近就足够了,那么就不需要 ObservableCollection<T>
了。但它就在那里。
我的主窗口上有一个列表框,其中包含以下 XAML
<Window x:Class="MVVMExample.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:MVVMExample"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox x:Name="listBox" HorizontalAlignment="Left" Height="241" Margin="24,48,0,0" VerticalAlignment="Top" Width="150" ItemsSource="{Binding Items}"/>
<Label x:Name="label" Content="Items" HorizontalAlignment="Left" Margin="24,17,0,0" VerticalAlignment="Top"/>
<Button x:Name="button" Content="Add Item" HorizontalAlignment="Left" Margin="194,140,0,0" VerticalAlignment="Top" Width="75" Command="{Binding AddItemCommand}"/>
</Grid>
</Window>
我有我的 MainWindowViewModel
using Prism.Commands;
using Prism.Mvvm;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
namespace MVVMExample
{
public class MainWindowViewModel : BindableBase
{
public ICommand AddItemCommand { get; set; }
private List<string> items;
public List<string> Items
{
get { return items; }
set { SetProperty(ref items, value); }
}
public MainWindowViewModel()
{
Items = new List<string>();
Items.Add("Item 1");
AddItemCommand = new DelegateCommand(ExecuteAddItem);
}
private void ExecuteAddItem()
{
Items.Add("Item 2");
}
}
}
据我了解,每当 属性 更改时,SetProperty 方法都会引发 INotifyPropertyChanged 事件。
每当我 运行 这个程序时,我都可以看到 MainWindow 上的列表框确实有项目 "Item 1" 但是当我按下添加项目按钮时,项目 "Item 2" 没有得到添加到 UI 尽管它确实被添加到项目列表中。
我知道如果我使用 ObservableCollection 而不是 List,我可以将 "Item 2" 添加到 ListBox。但是,如果我使用的是 SetProperty 方法,为什么使用 List 不起作用?
我是不是理解错了什么?
当您将新列表分配给 属性 时,您为 Items
发出的唯一通知是在 setter 中。此代码不会将新的 List<string>
实例分配给 Items
。它为 Items
调用 getter 并向列表中添加一个字符串。不会引发任何通知事件,因为您永远不会执行任何引发通知事件的代码。
Items.Add("Item 2");
这是您的 get
区块:
get { return items; }
它不会引发任何事件。无论如何,它在 List<String>.Add()
之前被调用。它怎么知道您打算做的下一件事是向列表中添加一个项目?也许你只是列举一下。如果它知道,在您添加项目之前引发事件有什么用?
List<String>.Add()
也不会引发任何事件。
如果您希望 UI 在您向集合中添加项目时得到通知,请使用 ObservableCollection<String>
。这就是 ObservableCollection<T>
存在的原因:所以有一个集合会在您添加或删除项目时通知 UI。如果仅仅有引发事件的代码的模糊接近就足够了,那么就不需要 ObservableCollection<T>
了。但它就在那里。