Search code examples
c#.netwpfcaliburn.micromultidatatrigger

Binding inside a XAML ResourceDictionary


I have a horrible feeling what I'm trying to do cannot be done, but here goes. Maybe there's a better way.

I have a ResourceDictionary in a separate file, being pulled into a UserControl (View):

<UserControl.Resources>        
    <ResourceDictionary Source="..\Resources.xaml"/>
</UserControl.Resources>

In the RD, I define some button styles, one of which includes a Condition, setting the Foreground to Red if the "IsCurrentFilter" converter returns True:

<Style x:Key="FilterButton" TargetType="Button" BasedOn="{StaticResource ButtonBase}">
    <Style.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Binding="{Binding Converter={StaticResource IsCurrentFilter}}" Value="True"/>
            </MultiDataTrigger.Conditions>
            <Setter Property="Foreground" Value="Red" />
        </MultiDataTrigger>
    </Style.Triggers>
</Style>

The converter is defined in the same RD, further up:

<util:IsCurrentFilterConverter x:Key="IsCurrentFilter" ViewModel="{Binding}"/>

The problem is that the converter has no access to the view model (which it requires to do its comparison), and the ViewModel property simply refuses to bind to anything. The error is...

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:(no path); DataItem=null; target element is 'IsCurrentFilterConverter' (HashCode=50804710); target property is 'ViewModel' (type 'Object')

...which kinda makes sense, as I understand it's not in the visual tree.

So, how can I bind to the view model inside this ResourceDictionary?


Solution

  • You're doing it wrong. A converter should not be bound to the viewmodel in this way. It should depend solely on its input value(s). Set up your button in such a way that the viewmodel is the button's data context or is available in a predictable place up the logical tree. Then your binding's converter can 'convert' the viewmodel into a boolean value. Even better, add a viewmodel property providing the desired boolean and bind to it instead.