命名约定下的可见性自动绑定

16

我非常喜欢Caliburn框架以及它的命名约定绑定方式,但惊讶的是,可见性并没有像“Can名称”约定那样使用绑定来保护操作。据我所知,当在Caliburn中显式地使用绑定时,才会使用BooleanToVisibilityConverter转换器,而不会像guard方法一样自动绑定。因此,我考虑修改源代码,使其自动绑定到类似于“bool? ControlNameIsVisible()”(null等于收缩)之类的内容。我想知道这是否是正确的方法,如果是,是否有人已经实现了它,并可以在这里分享。

2个回答

18
您可以使用这种方法,这是完全合理的。另一种方法是在您的视图模型上使用与布尔属性相同名称的边框。Caliburn.Micro将根据布尔属性的值设置边框的可见性。
<Border x:Name="ControlIsVisible">
  <TextBox x:Name="MyControl" ... />
</Border>

干得好。这可能不是所有情况下的“正确”解决方案,但这是一个很棒的提示。 - IAmTimCorey
对于那些不想在 UI 上添加额外控制的人,可以直接将可见性绑定到属性。这不会通过约定自动绑定,但它所需的代码与上面的大致相同,并且没有额外的包装控制。 - liang
你有任何例子吗? - Paul Mrozowski
1
@PaulMrozowski 我猜是这样的:<TextBox x:Name="MyControl" Visibility="{Binding ControlIsVisible, Converter={StaticResource boolToVisibility}}" - Eternal21
这个非常好用。在Caliburn.Micro框架内,我感觉它也自我记录了。我喜欢这个解决方案。 - Perry Tew

9
如果您需要一个通用解决方案,这是我最终得出的结论,基于:为Caliburn.Micro添加IsEnabled约定 请注意,重写BindActions和BindProperties以便您可以检查绑定到它们的操作的可见性。
    protected override void Configure()
    {
        base.Configure();

        ConventionManager.AddElementConvention<UIElement>(UIElement.VisibilityProperty, "Visibility", "VisibilityChanged");

        var baseBindProperties = ViewModelBinder.BindProperties;
        ViewModelBinder.BindProperties =
            (frameWorkElements, viewModel) =>
            {
                BindVisiblityProperties(frameWorkElements, viewModel);
                return baseBindProperties(frameWorkElements, viewModel);
            };

        // Need to override BindActions as well, as it's called first and filters out anything it binds to before
        // BindProperties is called.
        var baseBindActions = ViewModelBinder.BindActions;
        ViewModelBinder.BindActions =
            (frameWorkElements, viewModel) =>
            {
                BindVisiblityProperties(frameWorkElements, viewModel);
                return baseBindActions(frameWorkElements, viewModel);
            };

    }

    void BindVisiblityProperties(IEnumerable<FrameworkElement> frameWorkElements, Type viewModel)
    {
        foreach (var frameworkElement in frameWorkElements)
        {
            var propertyName = frameworkElement.Name + "IsVisible";
            var property = viewModel.GetPropertyCaseInsensitive(propertyName);
            if (property != null)
            {
                var convention = ConventionManager
                    .GetElementConvention(typeof(FrameworkElement));
                ConventionManager.SetBindingWithoutBindingOverwrite(
                    viewModel,
                    propertyName,
                    property,
                    frameworkElement,
                    convention,
                    convention.GetBindableProperty(frameworkElement));
            }
        }
    }

1
请注意,这对于Caliburn.Micro的深层属性绑定(例如Person_ControlName)无效。 - Govert
这在工具栏中非常有效。我可以在ToolBarTray中显示/隐藏整个工具栏,就像我可以在工具栏中启用/禁用单个项目一样。非常好!到目前为止,没有任何问题。我使用Caliburn.Micro越多,Visual Studio似乎就不那么神奇了。 - metaomniliquant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接