Привязка видимости элемента к свойству ViewModel с поддержкой во время разработки

У меня есть приложение WPF, использующее Caliburn.Micro. Я хочу иметь возможность накладывать на приложение кольцо тени и прогресса (из MahApps.Metro), когда Я хочу, чтобы приложение ждало выполнения некоторой работы в фоновом режиме.

То, что у меня есть на данный момент, действительно работает, но наложение всегда включено во время разработки. Мое окно ShellView выглядит так:

<Window ...>
    ...
    <Grid>
        ...
        <Rectangle x:Name="waitShadow" Fill="#3f000000" Stroke="Black" StrokeThickness="0" Visibility="{Binding IsWaiting, Converter={StaticResource BooleanToVisibilityConverter}}" Grid.RowSpan="2"/>
        <ContentControl ... Visibility="{Binding IsWaiting, Converter={StaticResource BooleanToVisibilityConverter}}">
            <Controls:ProgressRing ...> <!-- from MahApps.Metro -->
            </Controls:ProgressRing>
        </ContentControl>
    </Grid>
</Window>

Мой класс ShellViewModel имеет общедоступное логическое свойство IsWaiting, и когда я устанавливаю для него значение true, появляется тень и кольцо, и все отключается. Когда я устанавливаю его на false, он возвращается в нормальное состояние, поэтому привязка работает (я использую Fody с надстройку PropertyChanged). Единственная проблема заключается в том, что свойство Visibility не свернуто во время разработки.

Есть ли лучший способ иметь оверлей, который работает во время разработки?


person Rebecca Scott    schedule 06.12.2012    source источник
comment
ShellViewModel реализует INotifyPropertyChanged?   -  person sa_ddam213    schedule 06.12.2012
comment
Да, я использую Fody с PropertyChanged   -  person Rebecca Scott    schedule 06.12.2012
comment
Итак, вы просто хотите установить значение во время разработки?   -  person sa_ddam213    schedule 06.12.2012
comment
Да, текущая привязка Visibility по умолчанию не возвращается к Collapsed, как я думал.   -  person Rebecca Scott    schedule 06.12.2012


Ответы (2)


Вы можете установить FallbackValue на свою привязку, которая будет Collapse во время разработки.

Visibility="{Binding IsWaiting, Converter={StaticResource BooleanToVisibilityConverter}, FallbackValue=Collapsed}"

Вы также можете сделать IsWaiting DependancyProperty и установить там значение по умолчанию, но я считаю это самым простым решением.

person sa_ddam213    schedule 06.12.2012

FallbackValue не всегда работает, т. е. если ваш дизайнер фактически привязан к данным времени разработки, а FallbackValue фактически изменяет поведение привязки во время выполнения, что во многих ситуациях может быть нежелательным. Я сделал расширение разметки, которое позволяет дизайнерам возиться с пользовательским интерфейсом в дизайнере, не беспокоясь об испорченном поведении во время выполнения. Я писал об этом здесь: http://www.singulink.com/CodeIndex/post/wpf-visibility-binding-with-design-time-control

Его можно использовать следующим образом:

<Grid Visibility="{data:Value {Binding RootObject, Converter={StaticResource NullToVisibilityConverter}}, DesignValue=Visible}">
    <TextBlock Background="Red" Text="Testing visibility" />
</Grid>

Код для ValueExtension выглядит следующим образом (любые обновления или исправления ошибок будут публиковаться в блоге, поэтому я предлагаю проверять последнюю версию там):

public class ValueExtension : MarkupExtension
{
    public object DesignValue { get; set; } = DependencyProperty.UnsetValue;

    [ConstructorArgument("value")]
    public object Value { get; set; } = DependencyProperty.UnsetValue;

    public ValueExtension() { }

    public ValueExtension(object value)
    {
        Value = value;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
        var property = provideValueTarget.TargetProperty as DependencyProperty;
        var target = provideValueTarget.TargetObject as DependencyObject;

        if (target == null || property == null)
           return this;

        object value = DesignerProperties.GetIsInDesignMode(target) && DesignValue != DependencyProperty.UnsetValue ? DesignValue : Value;

        if (value == DependencyProperty.UnsetValue || value == null)
            return value;

        if (value is MarkupExtension)
            return ((MarkupExtension)value).ProvideValue(serviceProvider);

        if (property.PropertyType.IsInstanceOfType(value))
            return value;

        return TypeDescriptor.GetConverter(property.PropertyType).ConvertFrom(value);
    }
}
person Mike Marynowski    schedule 05.07.2016
comment
Это лучший ответ, он отлично работает для меня с источниками данных, привязанными ко времени разработки. Спасибо. - person jv_; 05.10.2016