WPF MVVM - 数据网格不更新子项的已更改属性
本文关键字:属性 更新 MVVM 数据 数据网 网格 WPF | 更新日期: 2023-09-27 17:56:31
我在MVVM应用程序内的WPF表单上有一个可编辑的数据网格。
用户可以在此页面上执行两种可能的操作,这些操作会导致其中一行中的某些数据发生更改。其中一个可编辑字段(已请求)可能会导致另一个属性发生更改,并且有一个样式触发器取决于其值:
public bool OverRequested
{
get
{
if(this.Requested > this.Volume)
{
return true;
}
return false;
}
}
在 XAML 中:
<DataGridTextColumn Header="Requested" Binding="{Binding Requested}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding OverRequested}" Value="true">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="ToolTip" Value="The requested volume is greater than the available volume" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
另一个是更新行后面的数据项并更改项上的值的按钮。
尽管数据网格本身可以响应更改(如果在基础 ObservableCollection 中添加或删除行,它会在 UI 中相应地更新),但对行下项的这些属性所做的更改不会更新。
我知道这是设计使然,从某种意义上说,对可观察集合中的项目的更改不会冒泡,必须特别关注,但我正在努力找出如何实现我想要的东西。
我已经尝试 - 正如其他地方所建议的那样 - 覆盖可观察集合上 CollectionChanged 的事件处理程序,以向其中的项目添加通知警报:
private void ObservableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (var item in e.NewItems)
{
(item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
}
}
}
但是里面的项不实现 INotifyPropertyChanged 接口 - 它们是实体框架对象,而不是 ViewModels。所以演员阵容失败了。
有没有办法实现这一点?由于只有两个属性要监视,我很乐意手动执行此操作 - 但即使调用 OnPropertyChanged(") 来更新 ViewModel 中的所有属性也不会导致数据网格中的属性刷新。
也许你可以用另一种方式尝试,使用转换器。我有一个应用程序可以做类似的事情。我通常需要一个测试应用程序来恰到好处地获得这些东西,但请尝试以下操作:
<DataGridTextColumn Header="Requested" Binding="{Binding Requested}">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Foreground">
<Setter.Value>
<MultiBinding Converter="{StaticResource OverRequestedForegroundMultiConverter}">
<Binding Path="Requested" />
<Binding Path="Volume" />
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="ToolTip">
<Setter.Value>
<MultiBinding Converter="{StaticResource OverRequestedTooltipMultiConverter}">
<Binding Path="Requested" />
<Binding Path="Volume" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
转换器看起来像这样:
public class OverRequestedForegroundMultiConverter : IMultiValueConverter
{
#region IValueConverter Members
public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value.Length == 2)
{
if (value[0] is int && value[1] is int)
{
int requested = (int)value[0];
int volume = (int)value[1];
if (requested > volume)
return Colors.Red;
}
}
return Colors.Gray; // Or whatever color you want
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
public class OverRequestedTooltipMultiConverter : IMultiValueConverter
{
#region IValueConverter Members
public object Convert(object[] value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value.Length == 2)
{
if (value[0] is int && value[1] is int)
{
int requested = (int)value[0];
int volume = (int)value[1];
if (requested > volume)
return "The requested volume is greater than the available volume";
}
}
return null;
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
不要忘记将转换器添加到您的 app.xaml:
<app:OverRequestedForegroundMultiConverter x:Key="OverRequestedForegroundMultiConverter" />
<app:OverRequestedTooltipMultiConverter x:Key="OverRequestedTooltipMultiConverter" />