问题描述
我的任务是创建一个新的布局控件,用于我们的 Windows 应用程序范围内,应该有两种不同的布局;在特定 Windows 上显示哪一个将基于依赖项属性。我从来没有做过这样的事情,但根据我的研究,似乎应该使用 Control
。为了了解这一点,我尝试创建新的 Control
,它会根据属性值显示 TextBox
或 Label
。我是按类创建的:
public class DetailsLayout : Control
{
public static readonly DependencyProperty OverlayProperty =
DependencyProperty.Register("Overlay",typeof(bool),typeof(DetailsLayout),new FrameworkPropertyMetadata(true));
public bool Overlay
{
get { return (bool)GetValue(OverlayProperty); }
set
{
OnPropertyChanged(nameof(Overlay));
SetValue(OverlayProperty,value);
}
}
static DetailsLayout()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DetailsLayout),new FrameworkPropertyMetadata(typeof(DetailsLayout)));
}
public DetailsLayout()
{
DefaultStyleKey = typeof(DetailsLayout);
}
在 MainWindow
我有:
<layout:DetailsLayout Overlay="False">
</layout:DetailsLayout>
对于测试,如果 Overlay = True
我想显示 TextBox
,如果 Overlay = False
它应该显示标签。为了做到这一点,我尝试了几件事。首先,我尝试创建两个 ControlTemplate
:
<ControlTemplate x:Key="OverlayTemplate">
<TextBox Text="This is the default (TRUE) layout (OVERLAY) with a textBox."/>
</ControlTemplate>
<ControlTemplate x:Key="PushTemplate">
<Label Content="This is the optional (FALSE) layout (PUSH) with a label."/>
</ControlTemplate>
然后通过样式定义使用这些:
<Style targettype="{x:Type layout:DetailsLayout}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate targettype="{x:Type layout:DetailsLayout}">
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style targettype="ContentControl">
<Setter Property="Template" Value="{StaticResource OverlayTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Overlay,UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="Template" Value="{StaticResource PushTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我也尝试使用 DataTrigger
's;一种具有默认值,另一种同时指定了两个值:
两个值
<Style targettype="{x:Type layout:DetailsLayout}">
<Style.Triggers>
<DataTrigger Binding="{Binding Overlay}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate targettype="{x:Type layout:DetailsLayout}">
<TextBox Text="This is the default (TRUE) layout (OVERLAY) with a textBox."/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Overlay}" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate targettype="{x:Type layout:DetailsLayout}">
<Label Content="This is the optional (FALSE) layout (PUSH) with a label."/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
默认
<Style targettype="{x:Type layout:DetailsLayout}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate targettype="{x:Type layout:DetailsLayout}">
<TextBox Text="This is the default layout (OVERLAY) with a textBox."/>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Overlay}" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate targettype="{x:Type layout:DetailsLayout}">
<Label Content="This is the optional layout (PUSH) with a label."/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
目标只是在加载控件时选择正确的模板。因此,一个窗口可能使用 <layout:DetailsLayout Overlay="True" />
之类的控件,另一个窗口将使用 <layout:DetailsLayout Overlay="False" />
,并且在第一个窗口中将显示 TextBox
,在第二个窗口中将显示 Label
显示。但是一旦显示,它就不需要更改,因为 Overlay
值仅在 XAML 中指定(没有控件会在运行时更改此值)。
最后,我还尝试使用 DataTemplate
代替 ControlTemplate
,如下所示:
<DataTemplate x:Key="OverlayTemplate">
<TextBox Text="This is the default (TRUE) layout (OVERLAY) with a textBox."/>
</ControlTemplate>
<DataTemplate x:Key="PushTemplate">
<Label Content="This is the optional (FALSE) layout (PUSH) with a label."/>
</ControlTemplate>
但这也不起作用。任何关于如何使简单示例工作的建议/示例将不胜感激,因为除了我已经尝试过的建议之外,我找不到任何其他建议。提前谢谢你。
解决方法
非常感谢 Clemens 帮助解决这个问题。解决方案是将 DataTrigger
中的绑定表达式从 Binding={Binding Overlay}
更改为 Binding={Binding Overlay,RelativeSource={RelativeSource Self}}
。