wpf 在 DataGridCell 的 CellEditingTemplate 中查找 TextBox

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13643950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:25:54  来源:igfitidea点击:

Finding a TextBox in a DataGridCell's CellEditingTemplate

c#wpfxaml

提问by Tommy Jakobsen

I have a problem in WPF of programatically accessing a textbox in a DataGridTemplateColumn.CellEditingTemplate, when the cell is selected and in editing mode.

I have a problem in WPF of programatically accessing a textbox in a DataGridTemplateColumn.CellEditingTemplate, when the cell is selected and in editing mode.

Here is the XAML of my DataGrid:

这是我的 DataGrid 的 XAML:

<DataGrid x:Name="OrderLinesGrid"
          Style="{StaticResource DataGridStyle}"
          SelectionMode="Single"
          SelectionUnit="Cell"
          ItemsSource="{Binding OrderLines}">
  <DataGrid.Columns>
    <DataGridTemplateColumn x:Name="NumberColumn"
                            Header="Varenr."
                            MinWidth="100">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding Number}" />
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
      <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
          <TextBox Text="{Binding Number}" />
        </DataTemplate>
      </DataGridTemplateColumn.CellEditingTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

How can I access that TextBox when the cell is selected? Here is a image showing the visual tree of the DataGrid if that can help you:

选择单元格时如何访问该文本框?如果可以帮助您,这是显示 DataGrid 的可视化树的图像:

DataGrid Visual Tree

DataGrid 可视化树

I have tried the following in a DataGridCell GotFocus event, but without luck. It simply returns NULL because it is not found.

我在 DataGridCell GotFocus 事件中尝试了以下操作,但没有运气。它只是返回 NULL,因为它没有被找到。

private void DataGridCellGotFocus(object sender, RoutedEventArgs e)
{
    var cell = sender as DataGridCell;
    var textBox = FindChild<TextBox>(cell, null);
}

Where the FindChild method is the following:

其中 FindChild 方法如下:

/// <summary>
/// Finds a Child of a given item in the visual tree. 
/// </summary>
/// <param name="parent">A direct parent of the queried item.</param>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="childName">x:Name or Name of child. </param>
/// <returns>The first parent item that matches the submitted type parameter. 
/// If not matching item can be found, 
/// a null parent is being returned.</returns>
public static T FindChild<T>(DependencyObject parent, string childName)
    where T : DependencyObject
{
    // Confirm parent and childName are valid. 
    if (parent == null) return null;

    T foundChild = null;

    int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < childrenCount; i++)
    {
        var child = VisualTreeHelper.GetChild(parent, i);
        // If the child is not of the request child type child
        T childType = child as T;
        if (childType == null)
        {
            // recursively drill down the tree
            foundChild = FindChild<T>(child, childName);

            // If the child is found, break so we do not overwrite the found child. 
            if (foundChild != null) break;
        }
        else if (!string.IsNullOrEmpty(childName))
        {
            var frameworkElement = child as FrameworkElement;
            // If the child's name is set for search
            if (frameworkElement != null && frameworkElement.Name == childName)
            {
                // if the child's name is of the request name
                foundChild = (T)child;
                break;
            }
        }
        else
        {
            // child element found.
            foundChild = (T)child;
            break;
        }
    }

    return foundChild;
}

I suspect it has something to do with the DataTemplate but I need some suggestions on how to select the TextBox child element?

我怀疑它与 DataTemplate 有关,但我需要一些关于如何选择 TextBox 子元素的建议?

回答by Dzmitry Martavoi

I think you you should avoid using VisualTreeHelperas much as possible. If i understood, you can encapsulate your login within CellEditingCommand

我认为你应该尽可能避免使用VisualTreeHelper。如果我理解,您可以将您的登录信息封装在CellEditingCommand

<DataGridTemplateColumn.CellEditingTemplate>
  <DataTemplate>
    <TextBox Text="{Binding Number}">
      <i:Interaction.Triggers>
        <i:EventTrigger EventName="GotFocus">
          <i:InvokeCommandAction Command="{Binding CellEditingCommand}" />
        </i:EventTrigger>
      </i:Interaction.Triggers>
    </TextBox>
  </DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>

Also you can use Behaviors

你也可以使用行为

UPD:

更新

<DataTemplate>
    <TextBox Text="{Binding Number}">
        <Interactivity:Interaction.Triggers>
            <Interactivity:EventTrigger EventName="Loaded">
                <TriggerActions:TakeFocusAction />
            </Interactivity:EventTrigger>
        </Interactivity:Interaction.Triggers>
    </TextBox>
</DataTemplate>

and trigger action

并触发动作

public class TakeFocusAction : TriggerAction<UIElement>
{
    protected override void Invoke(object parameter)
    {
        AssociatedObject.Focus();
    }
}

回答by s.lazukov

ContentPresenter presenter = e.Column.GetCellContent(e.Row);    
TextBox textBox = presenter.ContentTemplate.FindName("nameOfYourTextBox", presenter) as TextBox;

回答by Ramin

I think you should handle PreparingCellForEdit: Sth

我想你应该处理PreparingCellForEdit:Sth

void MainDataGrid_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e)
{
   TextBox tb = e.Column.GetCellContent(e.Row) as TextBox;
}

See: How to know while user editing the WPF DataGrid Cell is empty?

请参阅:如何知道用户编辑 WPF DataGrid 单元格时为空?