【问题标题】:Updating items inside a list in real time using the MVVM pattern使用 MVVM 模式实时更新列表中的项目
【发布时间】:2016-01-26 20:18:07
【问题描述】:

在我的 ViewModel 中有一个 ObservableCollection,它在 ViewModel 加载时填充。

public ObservableCollection<Price> ItemPrices
{
    get
    {
        return _itemPrices;
    }
    set
    {
        _itemPrices = value;
        OnPropertyChanged("ItemPrices");
    }
}

这绑定到一个 ListView,而 ListView 又包含一个用于布局的 GridView。 GridView 内的项目中有一个图像:

<ListView ItemsSource="{Binding ItemPrices}">
    <ListView.View>
        <GridView>

            <GridViewColumn Header="" Width="auto">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <Button Width="30" HorizontalAlignment="Right" Margin="5" CommandParameter="{Binding}"
                                Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.DocumentCommand}" >
                            <Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="{Binding Converter={StaticResource PriceDocumentImageConverter} }" />
                        </Button>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>

        </GridView>
    </ListView.View>
</ListView>

Source 中的 Binding 为我在这里想要做的事情提供了线索:根据绑定对象的属性之一的状态更改 Image 的源。我需要实时发生这种情况,因此,当用户更改相应的属性时,图像也会相应更改。

当此屏幕首次加载时,它会按预期工作。我根据对象的状态获得正确的图像源。但是,如果我通过 UI 更新对象,图像永远不会改变——即使我可以看到数据库中对象的状态正在改变。

我正在为 ItemPrices 引发相应的 OnPropertyChanged 事件。

起初,我认为使用转换器可能是错误的方法。所以我把它换成了触发器:

<Image HorizontalAlignment="Center" VerticalAlignment="Center">
    <Image.Style>
        <Style TargetType="{x:Type Image}">
            <Setter Property="Source" Value="/Resources/Icons/Document-Add.png" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding HasDocument}" Value="True">
                    <Setter Property="Source" Value="/Resources/Icons/Document-View.png" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>

但这也不起作用。

所以我想我会在保存后尝试刷新 ObservableCollection,然后返回数据库以获取我刚刚保存的一组新对象 - 但这也不起作用。

我以前做过这样的事情,但在这些情况下,我已经能够处理和更新集合中的单个项目 - 例如 SelectedItem,因为我希望在用户单击时更改某些内容它。

我做错了什么?

【问题讨论】:

  • ObservableCollection 里面已经有OnPropertyChanged 事件触发器,你可以去掉它。
  • HasDocument 调用 OnPropertyChanged 了吗?
  • @adminSoftDK 不 - 但我不知道如何才能提高一个。我想这是问题的一部分。它是一个计算属性,取决于 Price 对象是否具有附加的 Document 对象。但是在 ViewModel 上没有单个 Price 对象来引发事件,我应该在哪里发送通知?
  • 当任何其他属性(已关闭 HasDocument)更改调用 OnPropertyChanged("HasDocument") 时,您仍然可以为计算属性引发一个,并且它将为该属性引发它。它应该工作得很好。
  • 我明白了,在这种情况下,我知道有几种选择。您可以在视图模型上使用许多属性包装 EF 对象,每个属性都将返回 EF 属性,但 UI 将绑定到包装器。第二种选择(我的首选)是创建 EntityViewModel,然后在其属性上实现 InotifyPropertyChanged,然后使用类似 automapper 的东西来映射这两个实体。因此,在第二个选项中,您最终会为每个实体提供 2 个类,一个仅用于传输对象,另一个用于与您的视图交互。

标签: c# wpf mvvm


【解决方案1】:

当您需要替换整个集合时,在该访问器中使用 OnPropertyChanged() 非常有用。但是,它不会因属性更改而引发更改。

您需要在属性本身上调用 OnPropertyChanged()。

更新:

此外,可观察集合仅在“添加、删除项目或刷新整个列表时”触发更新

https://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx

【讨论】:

  • 谢谢,这就是我的假设。问题是:如何。我没有通过视图模型显示单个对象,只有集合。
  • 在对象访问器上添加 OnPropertyChanged 通知不会很疯狂。如果操作正确,通知应该会冒泡。
  • @MattThrower 简而言之,您的ObservableCollections 上通常没有设置访问器。可能有人已经说过了,但是你收藏中的项目需要实现INotifyPropertyChanged
猜你喜欢
  • 2017-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-23
  • 2022-01-04
  • 1970-01-01
  • 2015-06-25
相关资源
最近更新 更多