Reference to a TextBox inside a DataTemplate

我只是一个虾纸丫 提交于 2019-12-20 05:09:09

问题


How do I get a reference to a TextBox that's only defined inside a DataTemplate (assuming that I've just applied this DataTemplate to some cell in a grid).

So far I'm using the sender in the TextBox events to retrieve this.

Thanks, rui


回答1:


For getting the reference of a control inside a Data Template, handling the event and then using the sender is one of the available option. There is one more option that you can try:

in .xaml:

    <toolkit:DataGrid Name="datagrid" Margin="0,0,0,28" AutoGenerateColumns="False">
        <toolkit:DataGrid.Columns>
            <toolkit:DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/>
            <toolkit:DataGridTemplateColumn Header="Last Name">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding LastName}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
        </toolkit:DataGrid.Columns>
    </toolkit:DataGrid>
    <Button Height="22" VerticalAlignment="Bottom" Click="Button_Click" />

in .xaml.cs

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        InitializeMouseHandlersForVisual(datagrid);
    }

    public void InitializeMouseHandlersForVisual(Visual visual)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
        {
            Visual childVisual = (Visual) VisualTreeHelper.GetChild(visual, i);
            if (childVisual is TextBox)
                MessageBox.Show("textbox Found");
            // Recursively enumerate children of the child visual object.

            InitializeMouseHandlersForVisual(childVisual);
        }
    }

Hope this helps!!

Edit:

if you want to use x:Name then also you need to at least get the ContentPresenter and for getting ContentPresenter you need to go through the element tree. The updates you need to make are:

in .xaml:

    <DataTemplate>
        <TextBox x:Name="text" Text="{Binding LastName}"/>
     </DataTemplate>

in .xaml.cs

    public void InitializeMouseHandlersForVisual(Visual visual)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
        {
            Visual childVisual = (Visual) VisualTreeHelper.GetChild(visual, i);
            ContentPresenter myContentPresenter = childVisual as ContentPresenter;
            if (myContentPresenter != null)
            {
                // Finding textBlock from the DataTemplate that is set on that ContentPresenter
                DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
                if (myDataTemplate != null)
                {
                    TextBox myTextBox = (TextBox)myDataTemplate.FindName("text", myContentPresenter);
                    MessageBox.Show("textbox Found");
                }
            }
            InitializeMouseHandlersForVisual(childVisual);
        }
    }

Hope this helps!!




回答2:


Sorry, but you're doing it wrong.
There's no good reason why you should have a reference to elements inside a DataTemplate IMO. Moreover, there's really no good reason for you to ever register for a Control Event.

As part of the MVVM architecture we started looking at Data and Interactions.
On the Data side - everything is databound to the ViewModel.
On the interactions side - Using ICommands all events are wired up for commands.

So, in your TextBox example - why are you listening to textbox events? Use TwoWay DataBinding to learn when TextBox text change.
In another example in which events are justified, like button.Click? Use Button.Command="{Binding myCommand}" to have commands handle events.

The reason you're running into issues is because you're trying to force a round peg in a square hole.

-- Justin




回答3:


I agree with Justin.

But if for some reason binding to some property is problematic and you still need reference to a control inside data template in SILVERLIGHT ( above solution is suitable for WPF components ) you can do as follow:

TextBox textBox = null;

   if (datagrid.SelectedItem != null)
      textBox = datagrid.Columns[1].GetCellContent(datagrid.SelectedItem) as TextBox;

   if (textBox != null)
      MessageBox.Show(textBox.Text);


来源:https://stackoverflow.com/questions/1941773/reference-to-a-textbox-inside-a-datatemplate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!