2012-08-02 125 views
8

原則,我發展到單選按鈕綁定到幾乎任何一種巧妙的方法:錯誤使用標記擴展綁定時:未知屬性遇到在解析標記擴展

/// <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(); 
    } 
} 

例如,你可以用它來綁定單選按鈕一個字符串屬性,如下所示(這是一個衆所周知的錯誤,你必須對每個單選唯一的組名):

<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'}}"/> 

現在,我想用public static readonly對象稱爲Filter1Filter2作爲值我的Rad ioButtons。所以,我想:

<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}'}}"/> 

但是,這給了我一個錯誤:

Unknown property 'To' for type 'MS.Internal.Markup.MarkupExtensionParser+UnknownMarkupExtension' encountered while parsing a Markup Extension.

如果我刪除引號仍然出現錯誤。我究竟做錯了什麼?

回答

9
+1

第二個環節都有正確答案(我的意思是,簡單的答案)。我只需要定義一個構造函數'public TrueWhenEqual(object to){To = to; }'然後用'Converter = {local:TrueWhenEqual {x:Static local:ViewModelClass.Filter1}}}來調用轉換器。'' – Qwertie 2012-08-02 22:34:39

5

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}}" /> 
+0

笨重,但是很有效。實際上它不工作*,但它確實編譯(我懷疑下一個問題是在我的MVVM框架中,UpdateControls)。 – Qwertie 2012-08-02 22:29:00

+0

確認,這個解決方案沒有我的MVVM框架。但是,在MarkupExtension上定義構造函數是一個更好的解決方案。然後我將它重命名爲'TrueWhenEqualTo',它讀取更自然:'IsChecked = {{Binding Filter,Converter = {local:TrueWhenEqualTo {x:Static local:ViewModelClass.Filter1}}}''。當然,「自然」是一個相對術語; XAML對於外行人來說仍然看起來像胡言亂語; ^) – Qwertie 2012-08-03 19:57:12