gpt4 book ai didi

WPF MVVM INotifyPropertyChanged 实现 - 模型或 View 模型

转载 作者:行者123 更新时间:2023-12-03 09:24:42 24 4
gpt4 key购买 nike

我在 StackOverflow 和其他博客上阅读了很多关于在哪里实现 INotifyPropertyChanged 的​​辩论,但似乎有些情况下你必须在模型上实现它。这是我的场景 - 我正在寻找关于我的结论的反馈,或者我的方法是否错误。

我正在使用 ObservableDictionary ( ObservableDictionary ) 的这种实现,因为我需要使用该键的高性能查询。

在这本字典中,我放置了模型对象的集合。

在我的 VM 中,我声明了字典的一个实例(书籍)并在 XAML 中绑定(bind)到它。

    <tk:DataGrid AutoGenerateColumns="False" Grid.Row="1" ItemsSource="{Binding Mode=TwoWay, Path=Books.Store}" Grid.ColumnSpan="2" Margin="3">
<tk:DataGrid.Columns>
<tk:DataGridTextColumn Binding="{Binding Mode=TwoWay, Path=Value.Name}" MinWidth="100" Header="Name" />
<tk:DataGridTextColumn Binding="{Binding Mode=TwoWay, Path=Value.Details}" MinWidth="300" Header="Details" />
</tk:DataGrid.Columns>
</tk:DataGrid>

如果我在 VM 上为 Books 实现 INotifyPropertyChanged 并在代码中更改 Book 名称的值,则 UI 不会更新。

如果我在 VM 上为 Store 实现 INotifyPropertyChanged 并在代码中更改 Book 名称的值,则 UI 不会更新。

如果我在模型上实现 INotifyProperyChanged 并在代码中将值更改为书名,则 UI 会更新。

在第一种情况下不会触发 Changed 事件,因为没有调用 Dictionary setter,它是 Item (a Book)。

我是否遗漏了什么,因为如果这是正确的解释,如果我想要我的模型的一致通知,无论它们是直接来自 XAML 还是通过某种集合绑定(bind),我总是希望模型实现 INotifyProperyChanged。

顺便说一句,除了 dll 引用,我个人不认为 INotifyPropertyChanged 作为 UI 函数 - 认为它应该在更一般的 .net 命名空间中定义 - 我的 2 美分。

编辑从这里开始:

我们进行了一场很好的语义辩论,以至于我错过了问题的核心,所以在这里再次发布,但用一个非常简单的 MVVM 示例说明了我的问题。

型号:
public class Book
{
public string Title { get; set; )
public List<Author> Authors { get; set; }
}

public class Author
{
public string Name { get; set; }
}

数据提供者生成一些虚拟数据
public class BookProvider
{
public ObservableCollection<Book> GetBooks() {
ObservableCollection<Book> books = new ObservableCollection<Book>();

books.Add(new Book {
Title = "Book1",
Authors = new List<Author> { new Author { Name = "Joe" }, new Author { Name = "Phil" } }
});

books.Add(new Book {
Title = "Book2",
Authors = new List<Author> { new Author { Name = "Jane" }, new Author { Name = "Bob" } }
});

return books;
}
}

ViewModel
    public class BookViewModel : INotifyPropertyChanged
{
private ObservableCollection<Book> books;
public ObservableCollection<Book> Books {
get { return books; }
set {
if (value != books) {
books = value;
NotifyPropertyChanged("Books");
}
}
}

private BookProvider provider;

public BookViewModel() {
provider = new BookProvider();
Books = provider.GetBooks();
}

// For testing the example
public void MakeChange() {
Books[0].Title = "Changed";
}

public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(String info) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}

后面的 XAML 代码
通常不会这样 - 只是为了简单的例子
public partial class MainWindow : Window
{
private BookViewModel vm;

public MainWindow() {
InitializeComponent();

vm = new BookViewModel();
this.DataContext = vm;
}

private void Button_Click(object sender, RoutedEventArgs e) {
vm.MakeChange();
}
}

XAML
<Window x:Class="BookTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="242*" />
<RowDefinition Height="69*" />
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding Books}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}" />
<ListBox ItemsSource="{Binding Authors}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontStyle="Italic" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Grid.Row="1" Content="Change" Click="Button_Click" />
</Grid>

如上所述,当我单击按钮并更改第一本书中的值时,UI 不会更改。

但是,当我将 INotifyPropertyChanged 移动到模型时,它可以正常工作(UI 更新),因为更改是在模型属性 setter 中,而不是在 VM 中的 Books 中:
public class Book : INotifyPropertyChanged
{
private string title;
public string Title {
get { return title; }
set {
if (value != title) {
title = value;
NotifyPropertyChanged("Title");
}
}
}

public List<Author> Authors { get; set; }

public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(String info) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}

回到我最初的问题,如果不在模型中实现 INotifyPropertyChanged,我该如何实现呢?

谢谢。

最佳答案

请阅读this article .它解释了如何通过实现 INotifyPropertyChanged 来减少代码重复。在模型中。

关于WPF MVVM INotifyPropertyChanged 实现 - 模型或 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5285377/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com