【发布时间】: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 个类,一个仅用于传输对象,另一个用于与您的视图交互。