繁体   English   中英

通过INotifyPropertyChanged更新ListView的ItemsSource

[英]Updating ListView's ItemsSource via INotifyPropertyChanged

在回答其他问题的同时,我尝试了解一件事。 我有一个ListViewItemsSource绑定到我的页面的属性。 页面实现INotifyPropertyChangedDataContext设置,evrything工作,我可以看到我的列表在屏幕上呈现。 但是如果我在其中一个元素中更改某些内容并在整个集合中提升属性,则更改在屏幕上不可见,调用getter,因此绑定有效,但没有任何更改。

为什么会这样? 是否有任何内部ListView的 optmization正在进行?

XAML代码:

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView ItemsSource="{Binding Elements}" Height="400">
        <ListView.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" FontSize="16"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <Button Content="Modify item" Click="Button_Click"/>
</StackPanel>

代码背后:

public class MyItem
{
    public string Name { get; set; }
    public MyItem(string name) { this.Name = name; }
}

public sealed partial class MainPage : Page, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

    private List<MyItem> elements = new List<MyItem> { new MyItem("Standard"), new MyItem("Standard"), new MyItem("Standard") };
    public List<MyItem> Elements { get { Debug.WriteLine("Collection getter"); return elements; } }

    public MainPage()
    {
        this.InitializeComponent();
        this.DataContext = this;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        elements[1].Name = "Modified one";
        RaiseProperty(nameof(Elements));
    }
}

注意:我知道如何通过在MyItem类中实现InotifyPropertyChanged来使其工作。 我也知道当一个项目内部发生变化时重新加载整个集合是一个糟糕的模式。 我只想确保一些事情。


其他情况 - 看起来绑定是源对象的引用副本,这很清楚。 但有趣的是,当我绑定到字符串数组时:

public string[] Elements { get; } = new string[] { "Standard", "Standard", "Standard" };

private void Button_Click(object sender, RoutedEventArgs e)
{
    Elements[1] = "Modified one";
    RaiseProperty(nameof(Elements));
}

XAML中的修改: <TextBlock Text="{Binding}" FontSize="16"/>

然后调用RaiseProperty(nameof(Elements)); 即使不修改集合,也会更新视图。 那么为什么绑定在这种情况下以不同的方式工 它似乎只是返回数组而不检查更改。

是的,将调用getter,因为您正在调用RaiseProperty(nameof(Elements)) 但是没有什么会更新,因为属性Elements 没有变化 它仍然是完全相同的对象。 改变的是它的底层对象( elements[1] )的属性Name

这就是为什么在这种情况下需要在MyItem级别实现InotifyPropertyChanged

如果将Elements的类型更改为ObservableCollection<MyItem> 然后,当您向/从中添加/删除项目时,UI将更新。 但是如果底层MyItem的属性像上面那样改变了,那么UI仍将保持不变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM