WPF XAML中如何定义可复用绑定的Visibility变量简化UI显隐配置
WPF中XAML内定义可复用绑定变量的实现方法
有几种无额外侵入性的实现方案,可以满足你一次定义绑定、多处引用的需求:
方案1:通过样式复用绑定(零自定义代码,优先推荐)
这是WPF原生支持的标准实现方式,不需要编写任何自定义类,直接通过资源字典中的样式封装重复的绑定逻辑即可,后续修改规则只需要改一处:
<Window.Resources> <!-- 提前注册转换器 --> <BooleanToVisibilityConverter x:Key="BoolToVisibility" /> <!-- 和你原有代码一致的反向转换器 --> <local:BoolToVisibilityInversedConverter x:Key="BoolToVisibilityInversed" /> <!-- 定义执行时隐藏的通用样式 --> <Style x:Key="HideWhileExecuting" TargetType="FrameworkElement"> <Setter Property="Visibility" Value="{Binding Executing, Converter={StaticResource BoolToVisibilityInversed}}" /> </Style> <!-- 定义执行时显示的通用样式 --> <Style x:Key="ShowWhileExecuting" TargetType="FrameworkElement"> <Setter Property="Visibility" Value="{Binding Executing, Converter={StaticResource BoolToVisibility}}" /> </Style> </Window.Resources> <!-- 控件直接引用对应样式即可,不需要重复写绑定和转换器 --> <Button Style="{StaticResource HideWhileExecuting}" ... /> <TextBlock Style="{StaticResource HideWhileExecuting}" ... /> <Button x:Name="CancelButton" Style="{StaticResource ShowWhileExecuting}" ... />
样式的TargetType设为FrameworkElement之后,所有继承自FrameworkElement的UI元素(按钮、文本框、面板等)都可以直接引用这个样式,不需要为不同控件类型单独定义。
方案2:通过BindingProxy实现伪代码式的变量定义
如果你想要和你写的伪代码完全一致的、直接定义独立可复用值的效果,可以写一个全项目通用的简易绑定代理类,只需要写一次,之后所有XAML页面都能用:
// 放在项目通用工具类目录下即可 public class BindingProxy : Freezable { protected override Freezable CreateInstanceCore() => new BindingProxy(); public object Value { get => GetValue(ValueProperty); set => SetValue(ValueProperty, value); } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(object), typeof(BindingProxy), new PropertyMetadata(null)); }
这个类利用了WPF中Freezable对象可继承DataContext的特性,即使放在资源字典里也能正常拿到页面的绑定上下文,不会出现绑定失效的问题。使用方式和你写的伪代码几乎一致:
<Window.Resources> <BooleanToVisibilityConverter x:Key="BoolToVisibility" /> <local:BoolToVisibilityInversedConverter x:Key="BoolToVisibilityInversed" /> <local:BindingProxy x:Key="VisibleWhileExecuting" Value="{Binding Executing, Converter={StaticResource BoolToVisibility}}" /> <local:BindingProxy x:Key="HiddenWhileExecuting" Value="{Binding Executing, Converter={StaticResource BoolToVisibilityInversed}}" /> </Window.Resources> <!-- 直接绑定资源中代理对象的Value属性即可 --> <Button Visibility="{Binding Value, Source={StaticResource HiddenWhileExecuting}}" ... /> <TextBlock Visibility="{Binding Value, Source={StaticResource HiddenWhileExecuting}}" ... /> <Button x:Name="CancelButton" Visibility="{Binding Value, Source={StaticResource VisibleWhileExecuting}}" ... />
关于你构思的绑定Image属性的方案
你自己想到的把其他元素Visibility绑定到图标控件Visibility的方案是完全可以正常运行的,如果用这个方案,记得把两个图标控件的Width、Height设为0,IsHitTestVisible设为False,避免占用布局空间、拦截用户交互。只是这个方案需要额外在视觉树里插入两个没有实际展示作用的控件,整洁度不如前面两种方案,不作为优先选择。
内容的提问来源于stack exchange,提问作者Pasetchnik
相关产品推荐
相关产品推荐

