WPF MVVM数据绑定带参数?

3

我之前的问题似乎无法得到解答,所以我会自己提出建议。我正在寻找的功能是,当单元格中的数据被编辑时,让数据网格更改单元格的前景色(甚至背景色)。

我的模型大致如下:

Public class Shipment : PropertyChangedBase
{
    #region Fields
    private ShippingService.Shipment.lbnshipment _localShipment;
    private ShippingService.Shipment.lbnshipment _originalShipment;
    #endregion

    #region Properties
    public int ShipmentID
    {
        get { return _localShipment.ShipmentID; }
        set
        {
            if(value != _localShipment.ShipmentID)
            {
                _localShipment.ShipmentID = value;
                NotifyOfPropertyChange(() => ShipmentID);
            }
         }
    } 

    public Shipment(ShippingServices.Shipment.lbnShipment localshipment)
    {
        _originalShipment = localshipment;
        _localShipment = localshipment;
    }

    //This Section is my best guess solution, but it just a guess
    public Color HasChanged(string Property)
    {
        switch(Property)
        {
           case "ShipmentID":
               if(_localShipment.ShipmentID != _originalShipment.ShipmentID)
               {
                  return Colors.Red;
               } else {
                  return Colors.Black;
               }
               break;
        }
    }
}

我已经剥离了大部分属性,HasChanged现在纯属虚构,但我希望能够将DataGridTextColumn的Foreground(或背景,如果可能的话)绑定到这个HasChanged方法,并且以某种方式传递当前调用该方法的参数。
<DataGridTextColumn Header="ShipmentID" Binding="{Binding ShipmentID}" Foreground="{Binding HasChanged}" />

我希望有一个巧妙的方法可以让绑定知道哪个属性已更改,就像IDataErrorInfo允许每个属性都绑定验证一样。虽然我不知道它在后台是如何运作的。


你可以使用 IMultiValueConverter,将当前视图模型的属性和该视图模型副本的属性绑定起来。然后在转换器内部验证这些属性是否相等,并返回特定的颜色。 - Herdo
2个回答

7
它需要一个转换器,对吧?因此,您的绑定应如下所示:
<DataGridTextColumn.Foreground>
    <SolidColorBrush Color="{Binding Converter={StaticResource hasChangedConverter}, ConverterParameter='ShipmentID'}"/>
</DataGridTextColumn.Foreground>

您的转换器将如下所示(去除多余代码):
class HasChangedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var shipment = value as Shipment;
        var property = parameter as string;

        return shipment.HasChanged(property);
    }
}

更新: 使用如上所示的单引号将转换器参数括起来应该可以工作。如果不行,您可以使用绑定的扩展格式:

<SolidColorBrush.Color>
    <Binding Converter="{StaticResource hasChangedConverter}" ConverterParameter="ShipmentID"/>
</SolidColorBrush.Color>

更新 II: ... 显然我们不能随意更改DataGridTextColumn的背景,因此请将您的列的XAML更改为以下内容:

<DataGridTemplateColumn Header="ShipmentID">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding ShipmentID}">
                <TextBlock.Background> 
                    <SolidColorBrush Color="{Binding Path=ShipmentID, Converter={StaticResource HasChangedConv}}"/>
                </TextBlock.Background>
            </TextBlock>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

这一点的值实际上不是货运对象本身,而是字符串属性“ShipmentID”吗? - Ben
如果你写了 Foreground="{Binding ShipmentID, Converter=...}" 那么是的,它会有问题。但是如果省略 ShipmentID 这部分,那就不会有问题了。 - mcwyrm
太棒了,我会尝试一下的,这比我原来想的解决方案要干净得多 :D - Ben
糟糕!将字符串直接传递给转换器参数的方式与我展示的方式不同。我会更新答案。同时,此链接可能有所帮助: http://www.infosysblogs.com/microsoft/2008/04/wpf_passing_string_to_converte.html - mcwyrm
我现在从转换器中返回一个新的SolidColorBrush。快速谷歌搜索显示,您无法动态更改SolidColorBrush的颜色。但是,我现在遇到了一个非常相似的“找不到控制FrameworkElement”的错误。尽管文本可见,但它始终保持黑色。并且每当您编辑单元格时都会抛出此错误。 - Ben
显示剩余4条评论

1
有两个选项:
  • 如果这个属性是在UI中与ViewModel绑定的,您可以监听该属性在ViewModel中的更改,然后相应地更改颜色。

  • 如果没有,请使用命令系统。理想情况下:
    - UI向ViewModel发送一个Command,表示某些内容已更改。
    - ViewModel执行命令并更改Color字段。需要通知UI颜色已更改。

这里是ICommand接口的实现:

http://wpftutorial.net/DelegateCommand.html


嘿,谢谢回复。我实际上正在使用CM进行操作,因此命令很简单,但这意味着对于每个属性都需要有一个颜色属性(请注意,运输具有30个属性,并且我的意思是,ShipmentID,ShipmentNO等)。我希望有一个解决方案,可以避免在模型/视图模型上拥有如此多的额外属性。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接