9

In principle, I developed a neat way to bind RadioButtons to almost anything:

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

For example, you can use this to bind RadioButtons to a string property as follows (it is a well-known bug that you must use a unique GroupName for each RadioButton):

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

Now, I would like to use public static readonly objects called Filter1 and Filter2 as the values of my RadioButtons. So I tried:

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

But this gives me an error:

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

The error still occurs if I remove the quotes. What am I doing wrong?

3 Answers 3

9

It's a bug that can occur with nested MarkupExtensions. Try putting your custom Markup into a separate DLL/Project or use property element syntax.

Sign up to request clarification or add additional context in comments.

1 Comment

The second link has the correct answer (by which I mean, the easy answer). I simply have to define a constructor public TrueWhenEqual(object to) { To = to; } and then invoke the converter with Converter={local:TrueWhenEqual {x:Static local:ViewModelClass.Filter1}}}
6

WPF doesn't handle nested markup extensions too well. To overcome this, you can use your markup extension as an element. It's a bit clumsy and harder to read, but it works:

<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>

Another way would be to declare your converter and use it as a static resource:

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

2 Comments

Clunky, but it works. Well actually it doesn't work, but it does compile (I suspect the next problem is in my MVVM framework, UpdateControls).
Confirmed, this solution works without my MVVM framework. Defining a constructor on the MarkupExtension is a much better solution, though. Then I renamed it to TrueWhenEqualTo which reads more naturally: IsChecked="{Binding Filter, Converter={local:TrueWhenEqualTo {x:Static local:ViewModelClass.Filter1}}}". Of course, "naturally" is a relative term; XAML still looks like gibberish to the uninitiated ;^)
0

I encountered the same bug on a machine with .NET 4.6 installed. As soon as I updated to the .NET 4.7 (Developer Pack) this error gone without any code changes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.