Автосвязывание видимости с соглашением об именах - PullRequest
16 голосов
/ 09 июля 2011

Мне очень нравится Caliburn и обязательное соглашение об именах, и я был удивлен, что видимость не связана таким же образом, как Конвенция "CanNAME" используется для защиты действия.Насколько я знаю, BooleanToVisibilityConverter используется только тогда, когда Binding явно используется в Caliburn, а не автоматически, как метод guard.Поэтому я подумал изменить источник так, чтобы он автоматически связывался с «bool? ControlNameIsVisible ()» (null равно collapse) или аналогичным.Мне было интересно, если это правильный подход, и если да, если кто-то уже сделал реализацию и может поделиться здесь.

Ответы [ 2 ]

18 голосов
/ 09 июля 2011

Вы можете использовать этот подход, если хотите, это вполне разумно.Другой подход заключается в использовании Border с тем же именем, что и логическое свойство в вашей модели представления.Caliburn.Micro установит видимость Границы на основе значения логического свойства.

<Border x:Name="ControlIsVisible">
  <TextBox x:Name="MyControl" ... />
</Border>
9 голосов
/ 15 февраля 2013

Если вы хотите общее решение, вот что я закончил на основе: Добавление соглашения для 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));
            }
        }
    }
...