Search code examples
c#wpfarchitectureuser-controlsresourcedictionary

Getting access to MainWindow.xaml.cs properties from outsourced ResourceDictionary


I am working on a new UserControl lately and I have to make it customizable, which wasn't a problem until I figured out, that I have to put the DataTemplates in an external ResourceDictionary in order to make the Control even more customizable.

So what do I have? I have a very customizable UserControl, which is able to call a constructor with a so-called "templatePath" from which the ResourceDictionary will be loaded in the UserControl.Resources. Everything works just fine!

So what's the problem? The DataTemplates, which are now in a sepperate ResourceDictionary should be able to be bound to Properties of the UserControl.xaml(.cs) in order to check i.E. if a specific object is selected.

But that's not the only problem. Furthermore the UserControl has predefined Commands, that should be able to be bound to the DataTemplates. This wasn't a problem before when the DataTemplates were still in UserControl.xaml obviously.

The bad thing is, I really have to outsource the DataTemplates, because the control will be available to users only as .dll and in this case, there wouldn't be any opportunity to add custom Templates afterwards.

Does anybody have an idea of how I could implement this? Thanks in advance!

€dit: This would be, for example, the ResourceDictionary, which will be dynamically loaded when the UserControl will be displayed:

<ResourceDictionary 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:classes="clr-namespace:CustomControl"
>
<classes:CompareNodes x:Key="CompareNodes"/>

<Style x:Key="BorderHighlightStyle" TargetType="Border">
    <Setter Property="CornerRadius" Value="6"/>
    <Setter Property="BorderBrush" Value="Gray"/>
    <Setter Property="BorderThickness" Value="2"/>
    <Style.Triggers>
        <Trigger Property="IsMouseOver"  Value="True">
            <Setter Property="Background" Value="Azure"/>
        </Trigger>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Value="True">
                    <Condition.Binding>
                        <MultiBinding Converter="{StaticResource CompareNodes}">
                            <Binding RelativeSource="{RelativeSource Self}" Path="DataContext"/>
                            <Binding Source="{Binding ???????????}" Path="SelectedItem"/>
                        </MultiBinding>
                    </Condition.Binding>
                </Condition>
            </MultiDataTrigger.Conditions>
            <MultiDataTrigger.Setters>
                <Setter Property="Background" Value="LightGoldenrodYellow"/>
                <Setter Property="BorderBrush" Value="Black"/>
            </MultiDataTrigger.Setters>
        </MultiDataTrigger>
    </Style.Triggers>
</Style>
</ResourceDictionary>

As you see, I have no clue how I could bind to the SelectedItem-Property which is declared in UserControl.xaml(.cs).


Solution

  • I found a solution myself.

    I created a class called "BindableProperties", which has all Properties, that should be bindable from the outside (i.E. "SelectedItem") and some Commands. After that I added a "BindableProperties" object to my ResourceDictionary, which will then by loaded into my control.

    In my control, I read out the "BindableProperties"-Object from the ResourceDictionary and gave it the Commands I want to bind to. Everytime the selected item changes, the BindableProperties-Object gets a new "selectedItem", therefore it stays the same as in the control.

    The good thing is, that the object inside the class and the object in the ResourceDictionary are now the same, which allows me to bind to the Properties of "BindableProperties", which has the same properties as my UserControl.

    Problem solved.