【问题标题】:DataGrid catch cell value changed event with a single click on UpdateSourceTrigger = SourceUpdatedDataGrid 通过单击 UpdateSourceTrigger = SourceUpdated 捕获单元格值更改事件
【发布时间】:2013-11-24 11:47:22
【问题描述】:

我正在努力使用 DataGrid 捕捉事件。我想要实现的是,当用户在数据网格单元格的复选框上单击一次时,会触发一个事件,我可以获得当前单元格的值。但是,CellChangedEvent 仅在选择更改时触发,并且 CellEditingEvent 要么在单元格失去焦点时触发,要么永远不会触发。如果我尝试通过执行以下操作使复选框可通过单击修改,它永远不会触发:

<DataGrid Grid.ColumnSpan="2" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="True" ItemsSource="{Binding MasterDataTable, Mode=TwoWay}" CanUserAddRows="False" Margin="10 5" CurrentCellChanged="DataGrid_CurrentCellChanged">
            <DataGrid.Resources>
                <Style TargetType="DataGridCell">
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="IsEditing" Value="True" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.Resources>
        </DataGrid>

如何在用户单击单元格内的复选框后立即调用方法? 提前致谢。

【问题讨论】:

  • 您有单元格编辑模板或 DataGridColumn 要发布吗?我认为问题在于将其与单元格绑定值上的 UpdateSourceTrigger=PropertyChange 绑定。
  • 我希望我有,不幸的是我自动生成列。项目源绑定到 DataView 对象。
  • 好的,所以您首先需要的是不要自动生成您想要的列,这不是必须自定义的 DataGrid 的“特殊”行为,这是一种特殊行为,因为 DataGrid 的默认行为是更新绑定LostFocus 上的值,而不是常见的 PropertyChanged 设置。
  • 好的,我试试看。在不丢失使用 CellEditingFinished 事件的可能性的情况下单击单元格更改复选框值怎么样?
  • 既然你提到了它,我不相信 CellEditingFinished 会在失去焦点之前触发,你试图基于什么?为什么失去焦点对这件事不利?

标签: wpf events datagrid


【解决方案1】:

1) 在您的 DataGrid 中注册 TargetUpdated 事件。

2) 指定一个 Column ,最好设置 AutoGenerateColumns=False

3) 在您的 Binding 标志中,NotifyOnTargetUpdated 属性(您的目标是您的复选框)。

4) 在您的绑定中 UpdateSourceTrigger=PropertyChangedMode=TwoWay(不是 DataGrid 的默认行为)。

XAML:

 <DataGrid TargetUpdated="DataGrid_TargetUpdated" 
           AutoGenerateColumns="False" 
           ItemsSource="{Binding SomeValues, Mode=OneWay}"  CanUserAddRows="False"  >
    <DataGrid.Columns>
        <DataGridCheckBoxColumn Binding="{Binding Path=.,  NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Width="*"/>                        
    </DataGrid.Columns>
</DataGrid>

在 CS 中:(您可能不想处理该事件。)

   private void DataGrid_TargetUpdated(object sender, DataTransferEventArgs e)
   {
         // Do what ever...
   }  

【讨论】:

  • 感谢您的回答,但它部分工作。事实上,目标更新处理程序在加载用户未修改的数据时也会被调用。有什么解决方法吗?
  • 这是一个很好的问题,我们需要指示 ItemsSource 何时完全加载,以便我们可以在那里注册到 NotifyOnTargetUpdated。
  • 实际上我已经通过检查 CurrentCell 和 CurrentCell.Column 是否不为空来解决它(考虑到我只在应用程序启动后填充 DataGrid,否则我不知道该怎么做它)。非常感谢您的帮助。
  • 很高兴为您提供帮助,但您仍然提出了一个有趣的观点,当我发现我将如何发布更好、更完整的灵魂乐时。
  • 您的解决方案中是否必须有一个 CellEditTemplate 如果不是强制性的,您可以使用只有一个 CellTemplate 的 DataGridTemplateColumn,并且您不必处理维护 Edit 和 ReadOnly 的所有麻烦细胞的状态。
【解决方案2】:

我就是这样解决的。这不是最好的解决方案,但它对我有用。 正如@eranotzap 所说,我设置了 set AutoGenerateColumns=False 和 UpdateSourceTrigger = PropertyChanged。然后我做了以下事情:

<DataGrid Grid.ColumnSpan="2" Grid.Row="1" Grid.Column="0" 
          AutoGenerateColumns="False" 
          ItemsSource="{Binding MasterDataTable, Mode=TwoWay}" 
          CanUserAddRows="False" 
          Margin="10 5">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Path=Fornitore}" Header="Fornitore" Width="Auto" IsReadOnly="True" />
        <DataGridTextColumn Binding="{Binding Path=Stat}" Header="Stat" Width="Auto" IsReadOnly="True" />
        <DataGridTextColumn Binding="{Binding Path=Intestazione}" Header="Intestazione" Width="*" IsReadOnly="True" >
        <DataGridTextColumn.ElementStyle>
            <Style TargetType="TextBlock">
                <Setter Property="TextWrapping" Value="Wrap" />
            </Style>
        </DataGridTextColumn.ElementStyle>
        <DataGridTextColumn.EditingElementStyle>
            <Style TargetType="TextBox">
                <Setter Property="TextWrapping" Value="Wrap" />
                <Setter Property="AcceptsReturn" Value="true" />
            </Style>
        </DataGridTextColumn.EditingElementStyle>
        </DataGridTextColumn>
        <DataGridTextColumn Binding="{Binding Path=PrzVend}" Header="PrzVend" Width="Auto" IsReadOnly="True" />
        <DataGridTextColumn Binding="{Binding Path=DatEXPO}" Header="DatEXPO" Width="Auto" IsReadOnly="True" />
        <DataGridCheckBoxColumn Binding="{Binding Path=Sel, NotifyOnSourceUpdated=False, NotifyOnTargetUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Header="Sel" Width="Auto">
            <DataGridCheckBoxColumn.CellStyle>
                <Style TargetType="DataGridCell">
                    <EventSetter Event="CheckBox.Checked" Handler="CellChanged"/>
                    <EventSetter Event="CheckBox.Unchecked" Handler="CellChanged"/>
                    <Style.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True" />
                                <Condition Property="IsReadOnly" Value="False" />
                            </MultiTrigger.Conditions>
                            <Setter Property="IsEditing" Value="True" />
                        </MultiTrigger>
                    </Style.Triggers>
                </Style> 
            </DataGridCheckBoxColumn.CellStyle>
        </DataGridCheckBoxColumn>
        <DataGridTextColumn Binding="{Binding Path=CodComp}" Header="CodComp" Width="Auto" IsReadOnly="True" />
    </DataGrid.Columns>
</DataGrid>

在每次选中或取消选中复选框时,都会调用方法 CellChanges 背后的代码。要获得该值,我执行以下操作:

void CellChanged(object sender, RoutedEventArgs e)
{
    if (sender as DataGridCell != null && (sender as DataGridCell).Column != null && (sender as DataGridCell).Column.Header != null)
    {

        bool? isSelected = (e.OriginalSource as ToggleButton).IsChecked;

    }
}

希望它对某人有所帮助。

【讨论】:

    【解决方案3】:

    试试这个简单的方法

    private void myDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
        {
            if (e.Column.SortMemberPath.Equals("EndDate"))
            {
                if (((MyObjectInRow)e.Row.Item).DataFine.Equals(EndDate.MinValue))
                {
                    ((MyObjectInRow)e.Row.Item).Completed = 1;
                }
                else
                {
                    ((MyObjectInRow)e.Row.Item).Completed = 0;
                }
    
    
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      • 2014-07-15
      • 2015-05-05
      • 2013-05-01
      • 1970-01-01
      相关资源
      最近更新 更多