-1

How can I access my TextBox in button click event when both are in DataGrid Template Column? I can't access controls with x:Name and I can't seem to find a way.

XAML

<syncfusion:SfDataGrid x:Name="dataGrid" ItemsSource="{Binding Orders}" AllowEditing="True" AutoGenerateColumns="False">
    <syncfusion:SfDataGrid.Columns>
        <syncfusion:GridTextColumn MappingName="CustomerID"/>
        <syncfusion:GridTextColumn MappingName="CustomerName"/>
        <syncfusion:GridTemplateColumn MappingName="Country" SetCellBoundValue="True">
           <syncfusion:GridTemplateColumn.CellTemplate>
               <DataTemplate>
                   <TextBlock Text="{Binding Value}" />
               </DataTemplate>
            </syncfusion:GridTemplateColumn.CellTemplate>
            <syncfusion:GridTemplateColumn.EditTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="auto"/>
                        </Grid.ColumnDefinitions>
                       <TextBox Grid.Column="0" Text="{Binding Value}" syncfusion:FocusManagerHelper.FocusedElement="True" x:Name="txt" />
                       <Button Grid.Column="1" Margin="0 4 5 3" Content="..." Click="btn_Click" x:Name="btn"/>
                   </Grid>
               </DataTemplate>
           </syncfusion:GridTemplateColumn.EditTemplate>
       </syncfusion:GridTemplateColumn>
    </syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>

C#

private void btn_Click(object sender, RoutedEventArgs e)
{
    // Get TextBox here
}
Theo
  • 39
  • 4
  • Does your `Orders` collection contain `Order` Models or ViewModels? – ChrisBD Aug 05 '21 at 10:43
  • Why would you want to access the textbox from a button click? Is it to get the text? If so, that text should be available from the bound data item. It seems like you are trying to do something that was done in very old languages rather than how it is supposed to be done in WPF. – slugster Aug 05 '21 at 11:21
  • Bind the Button's Command property to an ICommand property of the view model item. Pass the current item to the ICommand by `CommandParameter="{Binding}"` on the Button. The item will now be passed to the `parameter` argument of the ICommand's Execute and CanExecute methods. – Clemens Aug 05 '21 at 11:50
  • Thank you, I'm new to wpf and I didn't know about commands. I got it to work. – Theo Aug 05 '21 at 13:57

1 Answers1

0

You can get the row and column index based on the mouse move pointer position by using GetVisualContainer method in SfDataGrid. Please refer the below code snippet,

//With the help of VisualContainer, you can get the row and column index based on the mouse move pointer position
var visualcontainer = this.dataGrid.GetVisualContainer();
// Gets the exact position where the mouse pointer is moved 
var point = Mouse.GetPosition(visualcontainer);
//Here you can get the row and column index based on the pointer position by using PointToCellRowColumnIndex() method
var rowColumnIndex = visualcontainer.PointToCellRowColumnIndex(point);

You can get the button clicked column element by using Items property in SfDataGrid.RowGenerator. Please refer the below code snippet,

if (!rowColumnIndex.IsEmpty)
{
            //get the columnElement
            var columnElement = 
  this.dataGrid.RowGenerator.Items.FirstOrDefault(x => x.RowIndex == rowColumnIndex.RowIndex).VisibleColumns[rowColumnIndex.ColumnIndex].ColumnElement;
            
}

You can get the TextBox by passing the column element in FindVisualChild and GetVisualChild method like below mentioned code snippet,

if (this.dataGrid.Columns[rowColumnIndex.ColumnIndex] is GridTemplateColumn)
{
      TextBox textBox = null;
      ContentPresenter contentPresenter = this.FindVisualChild<ContentPresenter>(columnElement);
       //get the TextBox
      textBox = GetVisualChild<TextBox>(contentPresenter);
}

C# Code Snippet related to GetVisualChild method:

private T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
        T child = default(T);
        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T;
            if (child == null)
            {
                child = GetVisualChild<T>(v);
            }
            if (child != null)
            {
                break;
            }
        }
        return child;
}

C# Code Snippet related to FindVisualChild method:

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

Sample Link: https://www.syncfusion.com/downloads/support/directtrac/general/ze/Sample-1045343101

KB Link: https://www.syncfusion.com/kb/12548/how-to-get-the-reference-of-the-control-added-inside-the-datatemplate-of-the