我怎样才能拥有一个只为默认的、未更改的控件可视树创建容器的 ControlTemplate?

Posted

技术标签:

【中文标题】我怎样才能拥有一个只为默认的、未更改的控件可视树创建容器的 ControlTemplate?【英文标题】:How can I have a ControlTemplate that only creates a container for the default, unaltered visual tree of a control? 【发布时间】:2015-01-19 18:26:31 【问题描述】:

我试图弄清楚如何将控件的模板更改为使其包含在 Grid 中的内容,如下所示:

<ControlTemplate x:Key="containedTemplate">
    <Grid>
        <!-- place templated control here -->
    </Grid>
</ControlTemplate>

我当然希望任何内部控件的属性都能自动与模板化控件同步。

这能做到吗?

这是TextBox 模板的假设示例:

<ControlTemplate x:Key="textTemplate" TargetType="x:Type TextBox">
    <Grid Background="Red">
        <TextBox Name="InnerTextBox" Margin="5,5,5,5"/>
    </Grid>
</ControlTemplate>

现在,如果我确实将模板应用于 TextBox 实例,如下所示:

<TextBox Text="Binding MyTextProperty" Template="StaticResource textTemplate"/>

...那么控件将神奇地成为一个Grid,包含一个带有一些边距的TextBox,其Text 的属性将绑定到MyTextProperty 的任何DataContext 实例已设置:

<!-- runtime visual tree I'd like to be produced by the above XAML -->
<Grid Background="Red">
    <TextBox Text="Binding MyTextProperty" Margin="5,5,5,5"/>
</Grid>

如果我有以下代码:

<StackPanel>
    <TextBox Text="Binding MyTextProperty" Template="StaticResource textTemplate"/>
    <TextBox Text="Binding MyOtherTextProperty" Template="StaticResource textTemplate"/>
    <TextBox Text="Binding YetAnotherTextProperty" Template="StaticResource textTemplate"/>
</StackPanel>

生成的树是这样的:

<!-- runtime visual tree I'd like to be produced by the above XAML -->
<StackPanel>
    <Grid Background="Red">
        <TextBox Text="Binding MyTextProperty" Margin="5,5,5,5"/>
    </Grid>
    <Grid Background="Red">
        <TextBox Text="Binding MyOtherTextProperty" Margin="5,5,5,5"/>
    </Grid>
    <Grid Background="Red">
        <TextBox Text="Binding YetAnotherTextProperty" Margin="5,5,5,5"/>
    </Grid>
</StackPanel>

在这些示例中,您可以看到TextBoxText 属性正确地向下传播到“内部”TextBox 实例。控件的默认可视化树也被保留(边框、输入区域等)。

我知道模板部分,但正如我所说,我正在尝试在这里找到一种全局方法,并且我想要更改控件的外观;只能放在容器中。

【问题讨论】:

你的问题还是不清楚 @safi 我改了标题。有更好的吗? 解释这个“只为默认创建一个容器” @safi 我的意思是我不想为控件重新创建整个可视化树,我只想要它默认情况下完全原样,但包含在另一个控件中控制作为其内容。我添加了一个示例,也许它有助于进一步理清问题。 【参考方案1】:

坦率地说,这个问题让我筋疲力尽,我只有这个答案,但不能说服我很多。

首先,您应该为要设置模板的每个控件创建多个 ControlTemplates,然后创建此类

public class ControlTemplateConverter

    public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(ControlTemplateConverter), new UIPropertyMetadata(false, IsEnabledChanged));

    private static void IsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    
        ControlTemplate t;
        if (d == null) return;
        if (d is TextBlock)
            t = App.Current.FindResource("TextBoxTemplate") as ControlTemplate;
        else if (d is CheckBox)
            t = App.Current.FindResource("CheckBoxTemplate") as ControlTemplate;
        // and So On

        (d as Control).Template = t;
    

    public static bool GetIsEnabled(DependencyObject obj)
    
        return (bool)obj.GetValue(IsEnabledProperty);
    
    public static void SetIsEnabled(DependencyObject obj, bool value)
    
        obj.SetValue(IsEnabledProperty, value);
    
 

你的控件应该是这样的:

<TextBox local:ControlTemplateConverter.IsEnabled="True"></TextBox>
<CheckBox local:ControlTemplateConverter.IsEnabled="True"></CheckBox>

【讨论】:

看来我的问题还不够清楚(英语不是我的主要语言)。我不需要动态创建模板的能力,我只想知道如何为控件创建一个模板,该模板将显示它包含在面板类型控件中,同时保持其属性同步。 如果有错误请纠正我。您想为 Grid 或任何面板设置某些内容,因此其中的每个控件都应放在网格内或您定义的模板内 等一下,我再创建一个例子。 那里,看看。恐怕我无法进一步解释。

以上是关于我怎样才能拥有一个只为默认的、未更改的控件可视树创建容器的 ControlTemplate?的主要内容,如果未能解决你的问题,请参考以下文章

我怎样才能只为第一个函数调用做某事?

我怎样才能拥有一个完全透明的 UIAlertView?

我怎样才能在春天拥有一个不是 bean 的数据源对象?

如何更改悬停时gridview内可用控件的工具提示的背景颜色

创建“非可视”.NET 用户控件

MPMoviePlayer默认控件按钮未对齐