【问题标题】:Error when binding using markup extensions: Unknown property encountered while parsing a Markup Extension使用标记扩展绑定时出错:解析标记扩展时遇到未知属性
【发布时间】:2012-07-31 21:12:53
【问题描述】:

原则上,我开发了一种将 RadioButtons 绑定到几乎任何东西的简洁方法:

/// <summary>Converts an value to 'true' if it matches the 'To' property.</summary>
/// <example>
/// <RadioButton IsChecked="{Binding VersionString, Converter={local:TrueWhenEqual To='1.0'}}"/>
/// </example>
public class TrueWhenEqual : MarkupExtension, IValueConverter
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    public object To { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return object.Equals(value, To);
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if ((bool)value) return To;
        throw new NotSupportedException();
    }
}

例如,您可以使用它来将 RadioButtons 绑定到字符串属性,如下所示(这是一个众所周知的错误,您必须为每个 RadioButton 使用唯一的 GroupName):

<RadioButton GroupName="G1" Content="Cat"
    IsChecked="{Binding Animal, Converter={local:TrueWhenEqual To='CAT'}}"/>
<RadioButton GroupName="G2" Content="Dog"
    IsChecked="{Binding Animal, Converter={local:TrueWhenEqual To='DOG'}}"/>
<RadioButton GroupName="G3" Content="Horse"
    IsChecked="{Binding Animal, Converter={local:TrueWhenEqual To='HORSE'}}"/>

现在,我想使用名为 Filter1Filter2public static readonly 对象作为我的 RadioButtons 的值。所以我尝试了:

<RadioButton GroupName="F1" Content="Filter Number One"
    IsChecked="{Binding Filter, Converter={local:TrueWhenEqual To='{x:Static local:ViewModelClass.Filter1}'}}"/>
<RadioButton GroupName="F2" Content="Filter Number Two"
    IsChecked="{Binding Filter, Converter={local:TrueWhenEqual To='{x:Static local:ViewModelClass.Filter2}'}}"/>

但这给了我一个错误:

类型的未知属性“To” 'MS.Internal.Markup.MarkupExtensionParser+UnknownMarkupExtension' 在解析标记扩展时遇到。

如果我删除引号,错误仍然会发生。我做错了什么?

【问题讨论】:

    标签: wpf xaml data-binding radio-button


    【解决方案1】:

    【讨论】:

    • 第二个链接有正确答案(我的意思是简单的答案)。我只需要定义一个构造函数public TrueWhenEqual(object to) { To = to; },然后使用Converter={local:TrueWhenEqual {x:Static local:ViewModelClass.Filter1}}}调用转换器
    【解决方案2】:

    WPF 不能很好地处理嵌套标记扩展。为了克服这个问题,您可以使用您的标记扩展作为一个元素。它有点笨拙且难以阅读,但它确实有效:

    <RadioButton GroupName="F1" Content="Filter Number One">
        <RadioButton.IsChecked>
            <Binding Path="Filter">
                <Binding.Converter>
                    <local:TrueWhenEqual To={x:Static local:ViewModelClass.Filter1} />
                </Binding.Converter>
            </Binding>
        </RadioButton.IsChecked>
    </RadioButton>
    

    另一种方法是声明您的转换器并将其用作静态资源:

    <Window.Resources>
        <local:TrueWhenEqual To={x:Static local:ViewModelClass.Filter1} x:Key="myConverter" />
    </Window.Resources>
    
    <RadioButton GroupName="F1" Content="Filter Number One"
                 IsChecked="{Binding Filter, Converter={StaticResource myConverter}}" />
    

    【讨论】:

    • 笨重,但它有效。好吧实际上它不工作,但它确实编译(我怀疑下一个问题是在我的 MVVM 框架中,UpdateControls)。
    • 已确认,此解决方案无需我的 MVVM 框架即可工作。不过,在 MarkupExtension 上定义构造函数是一个更好的解决方案。然后我将它重命名为TrueWhenEqualTo,读起来更自然:IsChecked="{Binding Filter, Converter={local:TrueWhenEqualTo {x:Static local:ViewModelClass.Filter1}}}"。当然,“自然”是一个相对术语; XAML 对于外行来说仍然看起来像胡言乱语;^)
    【解决方案3】:

    我在安装了 .NET 4.6 的机器上遇到了同样的错误。一旦我更新到 .NET 4.7(开发包),这个错误就消失了,没有任何代码更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-05
      • 2016-08-13
      • 2012-01-22
      • 2011-06-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多