正文
首先需要有一个左右方向的枚举:
/// <summary> /// 左右方向 /// </summary> public enum LeftRightOrientation { Left, Right }
然后在用户控件后台创建依赖属性 Orientation:
并准备好如下样式:
<!--#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 还需要用到,所以不去占用它。
下面来看使用方法。
在用户控件内部就是分别给面板以及内容控件设置对应的样式:
以及,前面提到的 RenderTransform 不被占用仍可使用的情况如下:
在外部使用用户控件时,只需在需要水平翻转的那个控件上设置 Orientation=”Right” 即可:
既然本次演示的都是 Sty.JudgeFlip.H.ContentControl.BindUc
,那么在 VM 中自然是需要也有一个 Orientation 属性的:
然后在用户控件后台代码中(DataContextChanged 时)同步它自己的以及 VM 的 Orientation 属性:
这样就可以愉快地玩耍啦。
此时有人可能就要说了,为什么不直接全部使用 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) 第一时间获取最新文章
发表评论