【问题标题】:How can I vary the layout of a UserControl by a Property?如何通过属性改变 UserControl 的布局?
【发布时间】:2017-07-02 07:20:49
【问题描述】:

我做了一个最小的项目来演示这个问题:

后面的代码:

public partial class AxisControl : UserControl
{
    public static readonly DependencyProperty LayoutProperty =
        DependencyProperty.Register("Layout", typeof(Orientation), typeof(AxisControl),
            new PropertyMetadata(Orientation.Horizontal));

    public Orientation Layout
    {
        get { return (Orientation)GetValue(LayoutProperty); }
        set { SetValue(LayoutProperty, value); }
    }

    public AxisControl()
    {
        InitializeComponent();
    }
}

Xaml:

<UserControl.Resources>
    <ContentControl x:Key="horizontalLayout" Height="60">
        <TextBlock Text="{Binding Layout, RelativeSource={RelativeSource AncestorType=UserControl}}" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
    </ContentControl>
    <ContentControl x:Key="verticalLayout" Width="60">
        <TextBlock Text="{Binding Layout, RelativeSource={RelativeSource AncestorType=UserControl}}" HorizontalAlignment="Left" VerticalAlignment="Center">
            <TextBlock.LayoutTransform>
                <RotateTransform Angle="-90"/>
            </TextBlock.LayoutTransform>
        </TextBlock>
    </ContentControl>
</UserControl.Resources>
<UserControl.Style>
    <Style TargetType="UserControl">
        <Style.Setters>
            <Setter Property="Content" Value="{StaticResource horizontalLayout}"/>
        </Style.Setters>
        <Style.Triggers>
            <DataTrigger Binding="{Binding Layout, ElementName=root}" Value="Vertical">
                <Setter Property="Content" Value="{StaticResource verticalLayout}"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Style>

编辑: Xaml 现在包含我想要在 UserControl 中排列的元素。

MainWindow Xaml:

<Grid>
    <local:AxisControl Layout="Vertical"/>
</Grid>

我们的想法是根据其 Layout 属性设置 UserControl 的布局,因此我将两个布局都放在静态资源中并制作了一个 Style 以根据 Orientation 类型的 Layout 将 Content 设置为我想要的内容。

编辑:我希望内容包含根据方向以不同顺序排列的元素。

UserControl 显示正确,但输出窗口中出现与我有关的错误:

找不到与引用“RelativeSource”绑定的源 FindAncestor, AncestorType='System.Windows.Controls.UserControl', 祖先级别='1''。绑定表达式:路径=布局;数据项=空; 目标元素是'TextBlock'(名称='');目标属性是“文本” (输入“字符串”)

这是否意味着它在可能来自触发器的可视化树中之前尝试进行绑定?

注意在 Bindings 中使用 RelativeSource 和 ElementName,因为将 DataContext 设置在 UserControl 的根目录是不正确的,因为它破坏了 DataContext 继承。

我做错了什么以及如何摆脱错误?

【问题讨论】:

  • 目前还不清楚您到底想要达到什么目的。 UserControl 是否意味着包含一个旋转或不旋转的 TextBlock,具体取决于 Layout 属性(实际上应该命名为 Orientation)?为什么要将 Resources 中 TextBlock 控件的 Text 属性绑定到 Layout 属性?
  • 有一点是肯定的。对于不同的布局,您不应该有不同的 TextBlock 资源。将 UI 元素作为资源通常是个坏主意。
  • 在主程序中,UserControl 是一个包含 TextBlock 的 ContentControl,并且在代码中有一些渲染来显示刻度线。我绑定 Text 属性来显示一些东西,主程序绑定到 Title 属性。

标签: wpf xaml data-binding user-controls


【解决方案1】:

受到 Clemens 评论和进一步研究的启发,我意识到我需要为每个布局提供一个 ControlTemplate 资源,而不是包含元素本身实例的资源。

<UserControl.Resources>
    <ControlTemplate x:Key="horizontalLayout">
        <Border Height="60" Background="LightBlue">
            <TextBlock Text="{Binding Layout, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
        </Border>
    </ControlTemplate>
    <ControlTemplate x:Key="verticalLayout" TargetType="UserControl">
        <Border Width="60" Background="LightBlue">
            <TextBlock Text="{Binding Layout, RelativeSource={RelativeSource TemplatedParent}}" HorizontalAlignment="Left" VerticalAlignment="Center">
                <TextBlock.LayoutTransform>
                    <RotateTransform Angle="-90"/>
                </TextBlock.LayoutTransform>
            </TextBlock>
        </Border>
    </ControlTemplate>
</UserControl.Resources>
<UserControl.Style>
    <Style TargetType="UserControl">
        <Style.Setters>
            <Setter Property="Template" Value="{StaticResource horizontalLayout}"/>
        </Style.Setters>
        <Style.Triggers>
            <DataTrigger Binding="{Binding Layout, ElementName=root}" Value="Vertical">
                <Setter Property="Template" Value="{StaticResource verticalLayout}"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Style>

布局 = 水平

布局 = 垂直

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-16
    • 1970-01-01
    • 2019-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多