设计时禁止绑定静态属性

4

每当可能时,我喜欢绑定到静态属性(例如,在不需要通知或模型已经实现INotifyPropertyChanged以用于其他目的时),例如:

Visibility="{Binding IsAdministractor, Source={x:Static local:User.Current}, Converter={local:FalseToCollapsedConverter}}"

问题在于这样的评估也适用于设计时,在与设计人员一起工作时会很困难。
正常绑定在设计时不起作用,我可以利用FallbackValue来指定仅在设计时使用的值(我从未在运行时使用FallbackValue)。
有没有一种简单的方法来使静态属性的绑定在设计时无效(禁用它们)?
我可以临时重命名属性,例如IsAdministrator123,但这很繁琐。

如果你创建DataContext或使用DesignInstance值,则普通绑定在设计时起作用。这通常使编码更容易(IntellisSense工作,立即预览等)。 - ASh
@ASh,我同意你可以这样做,但那需要太多的努力。无论如何,我不希望设计师向我展示运行时外观,因为我可以直接运行软件来查看。不确定“正常绑定在设计时不起作用”有多少不寻常。 - Sinatr
3个回答

2
你可以在转换器中或者静态的Current或者IsAdministractor属性中检查是否处于设计模式,然后返回你想要看到的状态。

编辑:

这里是一个MarkupExtension的代码(未经测试)。

public class BindingWithDesignSupport : MarkupExtension
{
    public BindingWithDesignSupport(){}

    public BindingWithDesignSupport(BindingBase binding)
    {
        Binding = binding;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return DesignerProperties.GetIsInDesignMode(new DependencyObject()) ? DesignTimeValue : Binding.ProvideValue(serviceProvider);
    }

    public BindingBase Binding { get; set; }

    public object DesignTimeValue { get; set; }
}

你应该能够像这样使用它:
Visibility="{BindingWithDesignSupport {Binding IsAdministractor, Source={x:Static local:User.Current}, Converter={local:FalseToCollapsedConverter}},DesignTimeValue=Visibility.Visible}"

在这种情况下使用转换器是个好主意,我之前没有想到过。但是如果没有转换器的绑定呢?我不想在每个公共静态属性的getter中添加样板代码。 - Sinatr
好的,_某处_你必须添加样板代码...关于没有转换器的绑定?你可以为它们添加一个转换器。这个转换器通常会返回未更改的值,并检查是否在设计模式下返回null或其转换器参数或任何你喜欢的内容。 - Markus Hütter
另一个评论针对“我喜欢尽可能地绑定静态属性”-那可能不是最佳实践...只是一个建议:使用一个好的MVVM框架,比如caliburn.micro。它可以简化很多事情。 - Markus Hütter
嗯,如果你想走那么远,你可能会发现使用MarkupExtension比使用converter更好,因为converter会增加绑定的计算时间,而MarkupExtension只需要一次性执行。 - Markus Hütter
很棒...我喜欢标记扩展的想法。这里有一个更详细的版本:Gist: BindingWithDesignSupport.cs - Terrence
显示剩余4条评论

0

您可以使用设计时数据将设计时视图模型置于所需的设计状态。

或者对于简单属性,您可以在视图模型中使用所需的设计时值进行初始化,例如:

    public bool IsAdministractor { get; set; } = true;

你漏了 static - Sinatr

0

可以将转换器附加到所有具有 FallbackValue(在设计时使用)和 Converter(提供运行时转换器)属性的属性:

public class RuntimeConverter : MarkupExtension, IValueConverter
{
    public object FallbackValue { get; set; }
    public IValueConverter Converter { get; set; }

    public RuntimeConverter() { }

    public override object ProvideValue(IServiceProvider serviceProvider) => this;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
            return FallbackValue;
        if (Converter == null)
            return value;
        return Converter.Convert(value, targetType, parameter, culture);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
            return FallbackValue;
        if (Converter == null)
            return value;
        return Converter.ConvertBack(value, targetType, parameter, culture);
    }
}

然后在设计时,可以更改静态属性返回的值:

<!-- split in multiple lines for readability -->
Visibility="{Binding IsPowerUser, Source={x:Static local:User.Logged},
    Converter={local:RuntimeConverter Converter={local:FalseToCollapsedConverter},
    FallbackValue=Collapsed}}">

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