可见性使用命名约定自动绑定

rid*_*sun 16 binding naming-conventions caliburn.micro

我非常喜欢Caliburn和命名约定绑定,并且惊讶于Visibility的绑定方式与"CanNAME"约定用于保护Action的方式不同.据我所知,只有在Caliburn中明确使用Binding时才使用BooleanToVisibilityConverter,而不是像guard方法那样自动使用.所以我想修改源代码以自动绑定到"bool?ControlNameIsVisible()"(null等于崩溃)或类似.我想知道这是否是正确的方法,如果有人已经完成了实施并且可以在这里分享它.

dev*_*tal 18

如果你愿意,你可以使用这种方法,这是完全合理的.另一种方法是在视图模型上使用与布尔属性同名的Border.Caliburn.Micro将根据布尔属性的值设置Border的可见性.

<Border x:Name="ControlIsVisible">
  <TextBox x:Name="MyControl" ... />
</Border>
Run Code Online (Sandbox Code Playgroud)


Mal*_*olm 9

如果你想要一个通用的解决方案,这就是我最终得到的,基于:将IsEnabled的约定添加到Caliburn.Micro

请注意覆盖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));
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)