我怎样才能拥有一个只为默认的、未更改的控件可视树创建容器的 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>
在这些示例中,您可以看到TextBox
的Text
属性正确地向下传播到“内部”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?的主要内容,如果未能解决你的问题,请参考以下文章