【问题标题】:Automatic editing of WPF datagrid content when datagrid-cell gets focus当 datagrid-cell 获得焦点时自动编辑 WPF 数据网格内容
【发布时间】:2015-03-25 23:01:37
【问题描述】:

我在 WPF 中有一个带有 DataGridTextColumDataGridTemplateColum 的数据网格。

<DataGridTextColumn Width="4*" IsReadOnly="True" x:Name="dataGridColumnDescription" 
Header="Description" Binding="{Binding Description}">
</DataGridTextColumn>

<DataGridTemplateColumn CellStyle="{StaticResource CellEditing}" IsReadOnly="False" Width="*" Header="Value" 
CellEditingTemplateSelector="{StaticResource myCellEditingTemplateSelectorValue}" 
CellTemplateSelector="{StaticResource myCellTemplateSelectorValue}">
</DataGridTemplateColumn>

CellTemplateSelectors 返回一个 DataTemplate 和一个用于 Celltemplate 的 TextBlock。用于单元格编辑的文本框!

<DataTemplate x:Key="dGridStringValueTemplate">
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Path=Value}"/>
</DataTemplate>

<DataTemplate x:Key="dGridStringValueTemplateEditing">
    <TextBox TextAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" BorderThickness="1" Text="{Binding Path=Value, UpdateSourceTrigger=LostFocus}"/>
</DataTemplate>

现在我想在 DataGridCell 获得焦点时自动聚焦 TextBox。用户应该能够在不双击单元格的情况下编辑 TextBox 内容。

我找到了这篇文章:

DataGrid Tips & Tricks: Single-Click Editing 在哪里可以获得当前 DataGridCell,但如何访问内容以使文本框获得焦点以编辑内容?

这是我的风格:

<Style x:Key="CellEditing" TargetType="{x:Type DataGridCell}">
    <EventSetter Event="PreviewMouseLeftButtonDown" Handler="myDataGridMain_PreviewMouseLeftButtonDown"></EventSetter>
</Style>

这是我的事件处理程序:

private void myDataGridMain_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DataGridCell cell = sender as DataGridCell;     // cell ist not null

    DataGridTemplateColumn col = cell.Column as DataGridTemplateColumn; //col is not null

    DataTemplate template = col.CellTemplate;  //this is null
}

如何使用该事件处理程序获取文本框?

【问题讨论】:

  • 当您希望您的网格始终可编辑时,为什么要编辑模板?只需在其中添加带有文本框的单元格模板并更改文本框本身的样式,这样您就不必编写焦点内容
  • @WPFKK 这行不通,因为数据网格不会切换到“编辑模式”,因此输入值不会绑定到源。

标签: c# wpf xaml datagrid


【解决方案1】:

这似乎有效:

    <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox  FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"></TextBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

【讨论】:

  • 感谢您的回答。与模板选择器结合使用,这不起作用:(
  • 谢谢你,你是伟大的巫师!
  • 我有一个带有组合和文本框的复杂 DataGrid。这个示例解决了我所有细胞类型的问题。
  • @HamedR 太棒了:)
【解决方案2】:

这种方法对我有用。它使用DataGrid 将始终在编辑开始时创建模板的新实例这一事实:

<DataGridTemplateColumn.CellEditingTemplate>
    <DataTemplate>
        <TextBox Text="{Binding MyProperty}" 
                 Loaded="TextBox_Loaded"></TextBox>
    </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

在后面的代码中:

private void TextBox_Loaded(object sender, RoutedEventArgs e)
{
    ((TextBox)sender).Focus();
    ((TextBox)sender).SelectAll();
}

作为额外的好处,它还选择单元格中的所有文本。无论您如何进入编辑模式(双击、单击、按 F2),它都应该可以工作

【讨论】:

    【解决方案3】:

    我管理它,不是最好的解决方案,但它有效...... 当 Cell 获得焦点时,我将其设置为编辑模式。

    private void myDataGridMain_OnFocus(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell != null)
            cell.IsEditing = true;
        //var test = FindVisualChild<TextBlock>(cell);
    }
    

    在 Keydown 上,我搜索视觉孩子并给予焦点。

    private void myDataGridMain_KeyDown(object sender, KeyEventArgs e)
            {
                DataGridCell cell = sender as DataGridCell;
    
                if (e.Key == Key.Enter)
                {   //give cell the focus
                    cell.Focus();
                }
                else
                {
                    if ((cell != null))
                    {
                        TextBox textbox = FindVisualChild<TextBox>(cell);
                        if (textbox != null)
                        {   //TextBox has benn found
                            if ((textbox as TextBox).IsFocused == false)
                            {
                                (textbox as TextBox).SelectAll();
                            }
                            (textbox as TextBox).Focus();
                        }
    
                        CheckBox chkbox = FindVisualChild<CheckBox>(cell);
                        if (chkbox != null)
                        {   //Checkbox has been found
                            (chkbox as CheckBox).Focus();
                        }
    
                        ComboBox combbox = FindVisualChild<ComboBox>(cell);
                        if (combbox != null)
                        {   //ComboBox has been found
                            (combbox as ComboBox).Focus();
                        }
                    }
                }
            }
    

    寻找视觉孩子!

    public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);
            if (child != null && child is T)
                return (T)child;
            else
            {
                T childOfChild = FindVisualChild<T>(child);
                if (childOfChild != null)
                    return childOfChild;
            }
        }
        return null;
    }
    

    【讨论】:

      【解决方案4】:

      创建从数据网格控件派生的新控件的简单答案

        using System.Windows.Controls;
      
         public class CustomDataGrid : DataGrid
         {
      
          protected override void OnSelectedCellsChanged(SelectedCellsChangedEventArgs e)
          {
              //to make sure cell is selected
              var cells = e.AddedCells.FirstOrDefault();
              if (cells != null)
              {
                  this.BeginEdit();
      
              }
              base.OnSelectedCellsChanged(e);
          }
      
         }
      

      【讨论】:

        【解决方案5】:

        Hisham's 建议非常适合我,但我会改用OnCurrentCellChanged,因为当SelectionUnitCellOrRowHeaderOnSelectedCellsChanged 将不起作用。在后一种情况下,BeginEdit() 只会在选择移动到另一行中的单元格时触发。向左或向右走完全不会触发事件。

        此外,最好在自定义控件中添加一个 DependencyProperty 并在触发BeginEdit() 之前对其进行检查,以防止这种行为(如其他 DataGrids 所做的那样,如 XCeed)。但这不是批评——只是我通常做的事情。

            protected override void OnCurrentCellChanged(EventArgs e)
            {
                // Make sure a cell is selected and only enter edit mode
                // if this is the desired behavior 
                if (CurrentCell != null && EditTrigger == EditTriggers.CellsCurrent)
                {
                    this.BeginEdit();
                }
                base.OnCurrentCellChanged(e);
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-26
          • 1970-01-01
          • 2015-07-21
          相关资源
          最近更新 更多