访问包含在数据模板中的控件

本文关键字:控件 包含 数据 访问 | 更新日期: 2023-09-27 18:14:45

我有一个ContentControl,用于在CollectionViewSource中显示当前项。

这个ContentControl使用了一个DataTemplate来显示一个RichTextBox。我想要访问的RichTextBox,所以我可以滚动到一个预定的位置。然而,我似乎无法访问它-我将如何获得对RichTextBox元素的引用?许多谢谢。

<CollectionViewSource x:Key="Results"
                      Source="{Binding Results}">
</CollectionViewSource>

<Grid.Resources>
    <!--Data Templates-->
    <DataTemplate DataType="{x:Type VFClass:Script}"
                  x:Key="scriptTemplate">
        <RichTextBox x:Name="ScriptViewRichTextBox"
                     local:RichTextBoxHelper.DocumentXaml="{Binding HighlightedRTF, IsAsync=False}"
                     BorderThickness="0"
                     ScrollViewer.CanContentScroll="True"
                     ScrollViewer.VerticalScrollBarVisibility="Auto"
                     IsReadOnly="{Binding ReadOnly}"
                     Margin="0"
                     ContextMenuOpening="RichTextBox_ContextMenuOpening"
                     Padding="5">
        </RichTextBox>
    </DataTemplate>
</Grid.Resources>

<ContentControl x:Name="ScriptText"
                Grid.Row="1"
                Margin="0"
                Content="{Binding IsAsync=False, Source={StaticResource Results}}"
                ContentTemplate="{StaticResource scriptTemplate}" />

访问包含在数据模板中的控件

使用VisualTreeHelper,您可以向下钻取可视化层次结构。假设你能接触到ContentControl。(递归地)使用VisualTreeHelper.GetChildrenCountVisualTreeHelper.GetChild访问ContentControl的实际视觉树,直到到达感兴趣的RichTextBox:

        int count = VisualTreeHelper.GetChildrenCount(contentControl);
        for (int i = 0; i < count; ++i)
        {
            DependencyObject d = VisualTreeHelper.GetChild(contentControl, i);
            if (d is RichTextBox)
            {
                //...do your thing
            }
            //  recurse (if necessary)...
        }

你可以使用模板的FindName函数,就像你在

后面的代码中写的那样
var template = ControlWhereTemplateAssign.Template;
var myControl = (RichTextBox)template.FindName("ScriptViewRichTextBox", ControlWhereTemplateAssign);

如果在Control上应用ControlTemplate而不是在ContentPresenter上应用DataTemplate,这将容易得多

因为模板是按名称分配的,所以这里可能不是问题。

从修改模板

开始
<ControlTemplate x:Key="scriptTemplate">
    <RichTextBox x:Name="ScriptViewRichTextBox"
                 ... >
    </RichTextBox>
</ControlTemplate>

指定为

<ContentControl x:Name="ScriptText"
                ...
                Template="{StaticResource scriptTemplate}">

作为

访问控件
    if (ScriptText.ApplyTemplate())
    {
        RichTextBox rtb = (RichTextBox)ScriptText.Template.FindName("ScriptViewRichTextBox", ScriptText);
    }

或(如果模板已经应用)

    RichTextBox rtb = (RichTextBox)ScriptText.Template.FindName("ScriptViewRichTextBox", ScriptText);

然而,FindName也适用于DataTemplate,但是有几个条件控制模板,所以你可能会遇到使用这个方法的异常

此操作仅对应用了此模板的元素有效。

使用ControlTemplate,你可以选择通过调用ApplyTemplate()方法手动应用模板,因此更安全的检索模板对象。