nikhil
nikhil

Reputation: 1748

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.

Upvotes: 0

Views: 1192

Answers (2)

mm8
mm8

Reputation: 169420

Use a TemplateBinding in the template. You may use a <Setter> to define the default value:

<Style x:Key="LightExpanderHeaderToggleButtonStyle" TargetType="ToggleButton">
    <Setter Property="Background" Value="{StaticResource BrushBeckmanAquaA1}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToggleButton">
                <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                    ...
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

You can then set or bind the Background of each instance of the control:

<uwpControls:Expander x:Name="ExpanderLisSharedSettings" Grid.Row="0" Background="Red" />

For example, if the view model defines a Brush property called "TheBackground", you could bind to it as usual (only UWP supports {x:Bind}):

<uwpControls:Expander x:Name="ExpanderLisSharedSettings" Grid.Row="0" 
                      Background="{Binding TheBackground}" />

Upvotes: 1

Faywang - MSFT
Faywang - MSFT

Reputation: 5868

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

Upvotes: 1

Related Questions