如何访问datagrid模板列文本框文本WPF C#

时间:2022-04-13 10:15:10

I need to access the text in a DataGrid's template column from code behind, but I don't know how. I need to change the text to whatever string I pass to it on the SelectionChanged event. Can someone please tell me how to achieve this? I found a similar question here but it had no answers.

我需要从后面的代码访问DataGrid的模板列中的文本,但我不知道如何。我需要将文本更改为我在SelectionChanged事件上传递给它的任何字符串。有人可以告诉我如何实现这一目标吗?我在这里发现了一个类似的问题,但它没有答案。

1 个解决方案

#1


14  

To find a control in a DataGrid template column, you should use FindChild():

要在DataGrid模板列中查找控件,应使用FindChild():

    public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
    {
        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);
            T childType = child as T;

            if (childType == null)
            {
                foundChild = FindChild<T>(child, childName);

                if (foundChild != null) break;
            }
            else
                if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;

                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        foundChild = (T)child;
                        break;
                    }
                    else
                    {
                        foundChild = FindChild<T>(child, childName);

                        if (foundChild != null)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    foundChild = (T)child;
                    break;
                }
        }

        return foundChild;
    }

For example I have this template column in MyDataGrid:

例如,我在MyDataGrid中有这个模板列:

<DataGridTemplateColumn Width="1.5*" IsReadOnly="False">
    <DataGridTemplateColumn.Header>
        <TextBlock Text="Sample" ToolTip="{Binding Path=Text, RelativeSource={RelativeSource Self}}" FontSize="14" />
     </DataGridTemplateColumn.Header>

     <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
             <TextBlock x:Name="MyTextBlock" Text="Hello!" />
         </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Access it from the code, you can:

从代码中访问它,您可以:

TextBlock MyTextBlock = FindChild<TextBlock>(MyDataGrid, "MyTextBlock");

MessageBox.Show(MyTextBlock.Text);

Note: Always use FindChild only when the control will be fully loaded, otherwise it will not find it and give null. In this case, I put this code in the event ContentRendered (Window) which says that all the contents of the window successfully load (even the event MyDataGrid_Loaded not have access to MyTextBlock, because it is not yet loaded):

注意:只有在控件完全加载时才使用FindChild,否则它将找不到它并给出null。在这种情况下,我将此代码放在事件ContentRendered(Window)中,该事件表明窗口的所有内容都成功加载(即使事件MyDataGrid_Loaded无法访问MyTextBlock,因为它尚未加载):

    private void Window_ContentRendered(object sender, EventArgs e)
    {
        TextBlock MyTextBlock = FindChild<TextBlock>(MyDataGrid, "MyTextBlock");

        MessageBox.Show(MyTextBlock.Text);
    }

EDIT1:

EDIT1:

To access the control of selected row to add event SelectionChanged to DataGrid in which to function, which will give a selected row:

要访问所选行的控件,将事件SelectionChanged添加到要运行的DataGrid,这将给出一个选定的行:

    private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        try
        {
            var row_list = GetDataGridRows(MyDataGrid);

            foreach (DataGridRow single_row in row_list)
            {
                if (single_row.IsSelected == true)
                {
                    TextBlock MyTextBlock = FindChild<TextBlock>(single_row, "MyTextBlock");

                    MessageBox.Show(MyTextBlock.Text);
                }
            }
        }

        catch 
        {
            throw new Exception("Can't get access to DataGridRow");
        }
    }

Listing of GetDataGridRows():

GetDataGridRows()的列表:

    public IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid)
    {
        var itemsSource = grid.ItemsSource as IEnumerable;

        if (null == itemsSource)
        {
            yield return null; 
        }

        foreach (var item in itemsSource)
        {
            var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;

            if (null != row)
            {
                yield return row; 
            }
        }
    }

EDIT2:

EDIT2:

To get ALL the items I rewrote the function FindChild():

要获取所有项目,我重写了函数FindChild():

    public static void FindChildGroup<T>(DependencyObject parent, string childName, ref List<T> list) where T : DependencyObject
    {
        // Checks should be made, but preferably one time before calling.
        // And here it is assumed that the programmer has taken into
        // account all of these conditions and checks are not needed.
        //if ((parent == null) || (childName == null) || (<Type T is not inheritable from FrameworkElement>))
        //{
        //    return;
        //}

        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);

        for (int i = 0; i < childrenCount; i++)
        {
            // Get the child
            var child = VisualTreeHelper.GetChild(parent, i);

            // Compare on conformity the type
            T child_Test = child as T;

            // Not compare - go next
            if (child_Test == null)
            {
                // Go the deep
                FindChildGroup<T>(child, childName, ref list);
            }
            else
            {
                // If match, then check the name of the item
                FrameworkElement child_Element = child_Test as FrameworkElement;

                if (child_Element.Name == childName)
                {
                    // Found
                    list.Add(child_Test);
                }

                // We are looking for further, perhaps there are
                // children with the same name
                FindChildGroup<T>(child, childName, ref list);
            }
        }

        return;
    }

Calling this new function:

调用这个新功能:

   private void Window_ContentRendered(object sender, EventArgs e)
   {
        // Create the List
        List<TextBlock> list = new List<TextBlock>();

        // Find all elements
        FindChildGroup<TextBlock>(MyDataGrid, "MyTextBlock", ref list);
        string text = "";

        // Print
        foreach (TextBlock elem in list)
        {
            text += elem.Text + "\n";
        }

        MessageBox.Show(text, "Text in TextBlock");
   }

Generally, this practice is not the best ... to get the items (such as all or selected), you can contact directly to the list which stores your data (like ObservableCollection). Also, it is useful events such as PropertyChanged.

一般来说,这种做法不是最好的...获取项目(如全部或选中),您可以直接联系到存储您的数据的列表(如ObservableCollection)。此外,它是有用的事件,如PropertyChanged。

#1


14  

To find a control in a DataGrid template column, you should use FindChild():

要在DataGrid模板列中查找控件,应使用FindChild():

    public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
    {
        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);
            T childType = child as T;

            if (childType == null)
            {
                foundChild = FindChild<T>(child, childName);

                if (foundChild != null) break;
            }
            else
                if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;

                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        foundChild = (T)child;
                        break;
                    }
                    else
                    {
                        foundChild = FindChild<T>(child, childName);

                        if (foundChild != null)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    foundChild = (T)child;
                    break;
                }
        }

        return foundChild;
    }

For example I have this template column in MyDataGrid:

例如,我在MyDataGrid中有这个模板列:

<DataGridTemplateColumn Width="1.5*" IsReadOnly="False">
    <DataGridTemplateColumn.Header>
        <TextBlock Text="Sample" ToolTip="{Binding Path=Text, RelativeSource={RelativeSource Self}}" FontSize="14" />
     </DataGridTemplateColumn.Header>

     <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
             <TextBlock x:Name="MyTextBlock" Text="Hello!" />
         </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Access it from the code, you can:

从代码中访问它,您可以:

TextBlock MyTextBlock = FindChild<TextBlock>(MyDataGrid, "MyTextBlock");

MessageBox.Show(MyTextBlock.Text);

Note: Always use FindChild only when the control will be fully loaded, otherwise it will not find it and give null. In this case, I put this code in the event ContentRendered (Window) which says that all the contents of the window successfully load (even the event MyDataGrid_Loaded not have access to MyTextBlock, because it is not yet loaded):

注意:只有在控件完全加载时才使用FindChild,否则它将找不到它并给出null。在这种情况下,我将此代码放在事件ContentRendered(Window)中,该事件表明窗口的所有内容都成功加载(即使事件MyDataGrid_Loaded无法访问MyTextBlock,因为它尚未加载):

    private void Window_ContentRendered(object sender, EventArgs e)
    {
        TextBlock MyTextBlock = FindChild<TextBlock>(MyDataGrid, "MyTextBlock");

        MessageBox.Show(MyTextBlock.Text);
    }

EDIT1:

EDIT1:

To access the control of selected row to add event SelectionChanged to DataGrid in which to function, which will give a selected row:

要访问所选行的控件,将事件SelectionChanged添加到要运行的DataGrid,这将给出一个选定的行:

    private void MyDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        try
        {
            var row_list = GetDataGridRows(MyDataGrid);

            foreach (DataGridRow single_row in row_list)
            {
                if (single_row.IsSelected == true)
                {
                    TextBlock MyTextBlock = FindChild<TextBlock>(single_row, "MyTextBlock");

                    MessageBox.Show(MyTextBlock.Text);
                }
            }
        }

        catch 
        {
            throw new Exception("Can't get access to DataGridRow");
        }
    }

Listing of GetDataGridRows():

GetDataGridRows()的列表:

    public IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid)
    {
        var itemsSource = grid.ItemsSource as IEnumerable;

        if (null == itemsSource)
        {
            yield return null; 
        }

        foreach (var item in itemsSource)
        {
            var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;

            if (null != row)
            {
                yield return row; 
            }
        }
    }

EDIT2:

EDIT2:

To get ALL the items I rewrote the function FindChild():

要获取所有项目,我重写了函数FindChild():

    public static void FindChildGroup<T>(DependencyObject parent, string childName, ref List<T> list) where T : DependencyObject
    {
        // Checks should be made, but preferably one time before calling.
        // And here it is assumed that the programmer has taken into
        // account all of these conditions and checks are not needed.
        //if ((parent == null) || (childName == null) || (<Type T is not inheritable from FrameworkElement>))
        //{
        //    return;
        //}

        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);

        for (int i = 0; i < childrenCount; i++)
        {
            // Get the child
            var child = VisualTreeHelper.GetChild(parent, i);

            // Compare on conformity the type
            T child_Test = child as T;

            // Not compare - go next
            if (child_Test == null)
            {
                // Go the deep
                FindChildGroup<T>(child, childName, ref list);
            }
            else
            {
                // If match, then check the name of the item
                FrameworkElement child_Element = child_Test as FrameworkElement;

                if (child_Element.Name == childName)
                {
                    // Found
                    list.Add(child_Test);
                }

                // We are looking for further, perhaps there are
                // children with the same name
                FindChildGroup<T>(child, childName, ref list);
            }
        }

        return;
    }

Calling this new function:

调用这个新功能:

   private void Window_ContentRendered(object sender, EventArgs e)
   {
        // Create the List
        List<TextBlock> list = new List<TextBlock>();

        // Find all elements
        FindChildGroup<TextBlock>(MyDataGrid, "MyTextBlock", ref list);
        string text = "";

        // Print
        foreach (TextBlock elem in list)
        {
            text += elem.Text + "\n";
        }

        MessageBox.Show(text, "Text in TextBlock");
   }

Generally, this practice is not the best ... to get the items (such as all or selected), you can contact directly to the list which stores your data (like ObservableCollection). Also, it is useful events such as PropertyChanged.

一般来说,这种做法不是最好的...获取项目(如全部或选中),您可以直接联系到存储您的数据的列表(如ObservableCollection)。此外,它是有用的事件,如PropertyChanged。