在DataGridCell的CellEditingTemplate中查找TextBox

时间:2012-11-30 11:03:14

标签: c# wpf xaml

我在WPF中遇到问题,在选择单元格并处于编辑模式时,以编程方式访问DataGridTemplateColumn.CellEditingTemplate中的文本框。

这是我的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>

如何在选择单元格时访问该TextBox?这是一个显示DataGrid可视化树的图像,如果它可以帮助您:

DataGrid Visual Tree

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

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

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;
}

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

3 个答案:

答案 0 :(得分:2)

我认为你应该尽量避免使用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>

您也可以使用Behaviors

<强> UPD

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

并触发操作

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

我认为你应该处理PreparingCellForEdit:Sth

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

请参阅:How to know while user editing the WPF DataGrid Cell is empty?