简体   繁体   English

WPF MVVM-Datagrid不会更新子项的更改属性

[英]WPF MVVM - Datagrid does not update changed properties of child items

I've got an editable datagrid on a WPF form inside an MVVM application. 我在MVVM应用程序内的WPF表单上有一个可编辑的数据网格。

There are two possible actions a user can take on this page that cause some data inside one of the rows to change. 用户可以在此页面上执行两种可能的操作,这些操作导致其中一行中的某些数据发生更改。 One of the editable fields - Requested - can cause another property to change, and there's a style trigger dependent on its value: 其中一个可编辑字段-请求-可能导致另一个属性发生更改,并且样式触发器取决于其值:

public bool OverRequested
{
    get
    {
        if(this.Requested > this.Volume)
        {
            return true;
        }
        return false;
    }
}

And in the XAML: 在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>

The other is a button that updates the data item behind the row and changes a value on the item. 另一个是按钮,用于更新该行后面的数据项并更改该项的值。

Although the datagrid itself is responsive to changes - if you add or remove rows from the underlying ObservableCollection it updates accordingly in the UI - changes to these properties on the items underneath the rows do not update. 尽管数据网格本身可以响应更改-如果您在基础ObservableCollection中添加或删除行,则它会在UI中相应地进行更新-对这些行下方项目的这些属性的更改不会更新。

I understand that this is by design, in the sense that changes to items inside an observableCollection do not bubble up, and have to be watched for specifically, but I'm struggling to find out how to achieve what I want. 我了解这是设计使然,在某种意义上说,对observableCollection中的项目所做的更改不会冒泡,必须特别注意,但是我正在努力寻找如何实现我想要的目标。

I've tried - as suggested elsewhere - overriding the event handler for CollectionChanged on the ObservableCollection to add a notification alert to the items inside: 我已经尝试-像其他地方建议的那样-覆盖ObservableCollection上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);
        }
    }
}

But items inside do not implement the INotifyPropertyChanged interface - they're Entity Framework objects and not ViewModels. 但是里面的项目没有实现INotifyPropertyChanged接口-它们是Entity Framework对象,而不是ViewModels。 So the cast fails. 因此强制转换失败。

Is there a way I can implement this? 有办法实现吗? With only two properties to watch, I'd happily do it manually - but even calling OnPropertyChanged("") to update all the properties in the ViewModel doesn't cause those inside the datagrid to refresh. 仅需要监视两个属性,我很乐意手动进行操作-但即使调用OnPropertyChanged(“”)来更新ViewModel中的所有属性也不会导致数据网格中的那些属性刷新。

Maybe you can try it another way, using converters. 也许您可以使用转换器尝试另一种方法。 I have an app that does something like that. 我有一个执行类似操作的应用程序。 I usually need a test app to get this stuff just right, but try this: 我通常需要一个测试应用程序来使这些东西正确无误,但是请尝试以下操作:

<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>

The converters would look something like this: 转换器看起来像这样:

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
    }

Don't forget to add the converters to your app.xaml: 不要忘记将转换器添加到您的app.xaml:

<app:OverRequestedForegroundMultiConverter x:Key="OverRequestedForegroundMultiConverter" />
<app:OverRequestedTooltipMultiConverter x:Key="OverRequestedTooltipMultiConverter" />

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

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