Search code examples
c#wpfxamluwp

Template binding inside a ResourceDictionary Control Template


I have a resource dictionary as follows,

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:uwpControls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    xmlns:controls="using:Presentation.Common.Controls">
<Style x:Key="ExpanderStyleSection" TargetType="uwpControls:Expander">
        <Setter Property="HeaderStyle" Value="{StaticResource LightExpanderHeaderToggleButtonStyle}"/>
        <Setter Property="Margin" Value="4"/>
    </Style>
 <Style x:Key="LightExpanderHeaderToggleButtonStyle" TargetType="ToggleButton">
 <Setter Property="Template">
 <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Grid x:Name="RootGrid" 
                                  Background="{StaticResource BrushBeckmanAquaA1}"> <!-- I want to change the background from an other View based on some condition -->
</ControlTemplate>
</Style>
</ResourceDictionary>

Now I am using the style inside this Dictionary as follows in an other view.

<uwpControls:Expander x:Name="ExpanderLisSharedSettings" Grid.Row="0" Style="{StaticResource ExpanderStyleSection}">
<!--Some Content here-->
</uwpControls:Expander

Whenever a property in the ViewModel changes, I want to update the RootGrid background in the ControlTemplate to some other color. How can I do it? In other words is there a way to create a dependency property of type Brush color and bind to the RootGrid Background in the ResourceDictionary. Please help.


Solution

  • You can create a ViewModel which contains a SolidColorBrush property and bind it with the Background of RootGrid and you need to declare the DataContext in the page which you use this style. In that case, it applies for Binding.

    If you want to use x:bind in ResourceDictionary, you need to create a code behind class for it. Since the x:Bind depends on code generation, so it needs a code-behind file containing a constructor that calls InitializeComponent (to initialize the generated code).

    Here we take binding as an example.

    Page.xaml:

    <ToggleButton Style="{StaticResource LightExpanderHeaderToggleButtonStyle}"></ToggleButton>
    

    Page.xaml.cs:

    public BlankPage1()
    {
        this.InitializeComponent();
        VM = new MyViewModel();
        VM.Fname = "fleegu";
        VM.MyColor = new SolidColorBrush(Colors.Green);
        this.DataContext = VM;
    }
    public MyViewModel VM { get; set; }
    

    ResourceDictionary.xaml:

    <Style x:Key="LightExpanderHeaderToggleButtonStyle" TargetType="ToggleButton">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Grid x:Name="RootGrid" Background="{Binding MyColor}">
                        <TextBlock Text="{Binding Fname}"></TextBlock>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    MyViewModel:

    public class MyViewModel: INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
    
        private string _fname { get; set; }
        private SolidColorBrush myColor { get; set; }
    
        public string Fname
        {
            get { return _fname; }
            set
            {
                _fname = value;
                this.OnPropertyChanged();
            }
        }
    
        public SolidColorBrush MyColor
        {
            get { return myColor; }
            set
            {
                myColor = value;
                this.OnPropertyChanged();
            }
        }
    
        public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }