简体   繁体   English

WPF DataGrid编辑后更新单元格样式

[英]WPF DataGrid updating cell style after editing

In XAML I have a column in a DataGrid that is defined like this: 在XAML中,我在DataGrid中有一列定义如下:

<DataGridTextColumn Header="Name" Binding="{Binding Name}">
  <DataGridTextColumn.CellStyle>
    <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}" >
      <Setter Property="Background" Value="{Binding Converter={StaticResource NameToBrushConverter}}"/>
    </Style>
  </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

The NameToBrushConverter returns a color when the "Name" column und the "FirstName" column have the same content. 当“名称”列和“名字”列具有相同的内容时,NameToBrushConverter返回一种颜色。 Otherwise it returns DependencyProperty.UnsetValue. 否则,它将返回DependencyProperty.UnsetValue。

The problem I'm facing is that if I edit a cell and end editing, the style is not updated. 我面临的问题是,如果我编辑单元格并结束编辑,则样式不会更新。 Only if the newly entered value moves to a different line (because of sorting) the conditional coloring of the background is applied. 仅当新输入的值移动到另一行(由于排序)时,才应用背景的有条件着色。 But if after editing the object is displayed in the same row of the datagrid the background color get's not updated until I click on sort. 但是,如果在编辑后对象显示在数据网格的同一行中,则直到我单击排序后,背景颜色才会更新。 As soon as the cell moves to a different row the background will be updated according to the Converter value. 单元格移动到另一行后,背景将根据Converter值进行更新。

Implementing INotifyPropertyChanged for the object doesn't help. 为该对象实现INotifyPropertyChanged并没有帮助。

Is there a way to tell the GridView that it has to reevaluate the styling after editing a cell? 有没有一种方法可以告诉GridView在编辑单元格后必须重新评估样式?


dataGrid.Items.Refresh();

Calling refresh helps, but which is the right event to trigger a refresh? 调用刷新有帮助,但是哪个事件触发刷新? I tried it in CellEditEnding but got an exception "Refresh is not allowed in AddNew- or EditItem transactions". 我在CellEditEnding中尝试过,但是出现了一个异常“ AddNew或EditItem事务中不允许刷新”。

1) You need to set UpdateSourceTrigger to PropertyChanged because it is by default set to LostFocus within a DataGrid. 1)您需要将UpdateSourceTrigger设置为PropertyChanged,因为默认情况下它在DataGrid中设置为LostFocus。

2) I'm guessing that you do not have a CellEditTemplate. 2)我猜您没有CellEditTemplate。

3) This is the biggest issue of all You would have to use multibinding on your properties with a relevant Converter. 3) 这是最大的问题。您必须使用相关的Converter对属性进行多重绑定。 The only reason this is working now is because when lost focus occurs the binding in the current cell refresh and gets your item (ie binding or binding to Path=.) passing it to the converter and outputting some color. 现在这样做的唯一原因是,当失去焦点时,当前单元格中的绑定将刷新,并使您的项(即绑定或绑定到Path =。)将其传递到转换器并输出某种颜色。

EDIT : 编辑:

I know see that i put the UpdateSourceTrigger on the wrong binding. 我知道我将UpdateSourceTrigger放在错误的绑定上。 Place it on the Name above and in your cellstyle also bind to Name. 将其放在上方的名称上,并在您的单元格样式中也绑定到名称。

XAML : XAML:

 <DataGrid>
       <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}">
                <DataGridTextColumn.CellStyle>
                       <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}" >
                      <Setter Property="Background" Value="{Binding Name ,Converter={StaticResource NameToBrushConverter}}"/>
                       </Style>
                </DataGridTextColumn.CellStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
   </DataGrid> 

Further more, as for your question below. 此外,关于您的以下问题。 The only reason it was working in partially when moving between rows is because of the default UpdateSourceTrigger for every binding nested in a DataGrid. 当在行之间移动时,它部分起作用的唯一原因是因为嵌套在DataGrid中的每个绑定都具有默认的UpdateSourceTrigger。 which is LostFocus. 这是LostFocus。

When Binding to the current DataContext using 当使用绑定到当前DataContext时

  <SomeElement Tag={Binding} />
  Or 
  <SomeElement Tag={Binding Path=.} />        

You are not binding to a property. 您没有绑定到属性。

The Binding is evaluated when : 在以下情况下评估绑定:

1) The DependencyObject initializes and all it's DP's are evaluated. 1)DependencyObject初始化,并评估其所有DP。 It gets it's value for the first time. 它第一次获得了价值。

2) UpdateSourceTrigger=LostFocus (The default inside the DataGrid) it is eventuated on LostFocus. 2)UpdateSourceTrigger = LostFocus(DataGrid内部的默认值),它最终出现在LostFocus上。 This is why your Binding is evaluated when you pass between rows. 这就是为什么在行之间传递时评估绑定的原因。

3) UpdateSourceTrigger=PropertyChanged. 3)UpdateSourceTrigger =属性更改。 If you wan't it on your datacontext you would have to explicitly set a property which would return itself and call it when the name property changes. 如果您不想在数据上下文中使用它,则必须显式设置一个属性,该属性将返回自身并在name属性更改时调用它。

Something like this : 像这样的东西:

CS : CS:

public class Entity : INotifyPropertyChanged
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Name"));
            PropertyChanged(this, new PropertyChangedEventArgs("Self"));
        }
    }


    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
            PropertyChanged(this, new PropertyChangedEventArgs("Self"));
        }
    }


    public Entity Self
    {
        get { return this; }
    }


    public event PropertyChangedEventHandler PropertyChanged = delegate { };
}

XAML : XAML:

     <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}" >
          <Setter Property="Background" Value="{Binding Self,Converter={StaticResource NameToBrushConverter}}"/>
      </Style>

But this won't evaluate on LostFocus, but you wouldn't need it to any ways since it will evaluate the first time and then on any changes to name. 但这不会在LostFocus上进行评估,但是您将不需要任何方式,因为它将首先评估,然后对名称进行任何更改。

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

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