WPF 用户控件翻转与内部的内容控件反翻转

WPF 用户控件翻转与内部的内容控件反翻转

WPF 用户控件翻转与内部的内容控件反翻转

独立观察员 2024年8月28日

正文

首先需要有一个左右方向的枚举:

/// <summary>
/// 左右方向
/// </summary>
public enum LeftRightOrientation
{
    Left,
    Right
}

 

然后在用户控件后台创建依赖属性 Orientation:

%title插图%num

 

并准备好如下样式

<!--#region 翻转 -->

<Style x:Key="Sty.JudgeFlip.H.Panel" TargetType="Panel">
    <Setter Property="RenderTransform">
        <Setter.Value>
            <ScaleTransform ScaleX="1"/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Orientation, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="Right">
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <ScaleTransform ScaleX="-1"/>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
<Style x:Key="Sty.JudgeFlip.H.ContentControl.BindUc" TargetType="ContentControl">
    <Setter Property="LayoutTransform">
        <Setter.Value>
            <ScaleTransform ScaleX="1"/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Orientation, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="Right">
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <ScaleTransform ScaleX="-1"/>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
<Style x:Key="Sty.JudgeFlip.H.ContentControl.BindVm" TargetType="ContentControl">
    <Setter Property="LayoutTransform">
        <Setter.Value>
            <ScaleTransform ScaleX="1"/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Orientation}" Value="Right">
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <ScaleTransform ScaleX="-1"/>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

<!--#endregion-->

 

其中 Sty.JudgeFlip.H.Panel 作用于 Panel,绑定用户控件的 Orientation 属性,当值为 Right 时,进行水平翻转。

Sty.JudgeFlip.H.ContentControl.BindUc 和 Sty.JudgeFlip.H.ContentControl.BindUc 都是作用于 ContentControl;前者绑定判断用户控件的 Orientation 属性,后者是直接绑定的 Orientation,也就是判断的是 DataContext 或者说 ViewModel 的 Orientation 属性(需要自行添加,下文会提到); 里面内容和功能基本和 Sty.JudgeFlip.H.Panel 一致,配合使用可达到整个控件翻转,里面的内容再翻转回来(避免文字等被翻转)的效果。

针对于 ContentControl 的样式,内部使用的是 LayoutTransform 而不是 RenderTransform,是考虑到 RenderTransform 可能 ContentControl 还需要用到,所以不去占用它。

 

下面来看使用方法。

 

在用户控件内部就是分别给面板以及内容控件设置对应的样式:

%title插图%num

 

以及,前面提到的 RenderTransform 不被占用仍可使用的情况如下:

%title插图%num

 

在外部使用用户控件时,只需在需要水平翻转的那个控件上设置 Orientation=”Right” 即可:

%title插图%num

 

既然本次演示的都是 Sty.JudgeFlip.H.ContentControl.BindUc ,那么在 VM 中自然是需要也有一个 Orientation 属性的:

%title插图%num

 

然后在用户控件后台代码中(DataContextChanged 时)同步它自己的以及 VM 的 Orientation 属性:

%title插图%num

 

这样就可以愉快地玩耍啦。

此时有人可能就要说了,为什么不直接全部使用 ViewModel 中的相关属性呢?这是因为如果不使用控件后台代码的方向属性,那么在设计视图则不会有翻转的效果,换句话说,如果你有左右两个对称的控件,那么在设计视图中,它们可能都是 “左脚” 的形式,这样就不利于控件的排布设计等。当然,你可以使用设计时 DataContext 等技术,但是那样好像更麻烦了。

 

最后说一句,本文介绍的是水平翻转的情况,而对于垂直翻转的情况,其道理是相同的。

 

更新

2024年9月13日

内容控件的两个样式可以改为针对 FrameworkElement,并更改 Key 名称:

<Style x:Key="Sty.JudgeFlip.H.Panel" TargetType="Panel">
    <Setter Property="RenderTransform">
        <Setter.Value>
            <ScaleTransform ScaleX="1"/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Orientation, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="Right">
            <Setter Property="RenderTransform">
                <Setter.Value>
                    <ScaleTransform ScaleX="-1"/>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
<Style x:Key="Sty.JudgeFlip.H.Content.BindUc" TargetType="FrameworkElement">
    <Setter Property="LayoutTransform">
        <Setter.Value>
            <ScaleTransform ScaleX="1"/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Orientation, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="Right">
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <ScaleTransform ScaleX="-1"/>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
<Style x:Key="Sty.JudgeFlip.H.Content.BindVm" TargetType="FrameworkElement">
    <Setter Property="LayoutTransform">
        <Setter.Value>
            <ScaleTransform ScaleX="1"/>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Orientation}" Value="Right">
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <ScaleTransform ScaleX="-1"/>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

 

 

原创文章,转载请注明: 转载自 独立观察员(dlgcy.com)

本文链接地址: [WPF 用户控件翻转与内部的内容控件反翻转](https://dlgcy.com/wpf-usercontrol-flip-and-contentcontrol-anti-flip/)

关注微信公众号 独立观察员博客(DLGCY_BLOG) 第一时间获取最新文章

%title插图%num

发表评论