如何通过属性更改UserControl的布局?

时间:2017-07-02 07:20:50

标签: wpf xaml data-binding user-controls

我做了最小的项目来证明这个问题:

代码背后:

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>

我们的想法是根据其布局属性设置UserControl的布局,因此我将两个布局放在静态资源中,并根据布局类型为方向设置样式将内容设置为我想要的布局。

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

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

  

找不到引用'RelativeSource的绑定源   FindAncestor,AncestorType ='System.Windows.Controls.UserControl',   AncestorLevel = '1'”。 BindingExpression:路径=布局;的DataItem = NULL;   target元素是'TextBlock'(Name ='');目标属性是'文字'   (输入'String')

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

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

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

1 个答案:

答案 0 :(得分:0)

受到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>

布局=水平

Layout = Orientation.Horizontal

布局=垂直

enter image description here