Search code examples
c#xamlwindows-phonewindows-8.1resourcedictionary

How to change an Image in a Setter Value in Windows Phone programatically


I have a resource defined in a resource dictionary that looks like this:

<x:Int32 x:Key="HubSectionHeaderCharacterSpacing">-10</x:Int32>
<x:Double x:Key="HubSectionHeaderFontSize">19</x:Double>
<Thickness x:Key="HubSectionHeaderMarginThickness">-1,5,0,31.5</Thickness>
<Thickness x:Key="HubSectionMarginThickness">19,0,0,0</Thickness>
<Style x:Key="MainMenuHubSectionStyle2" TargetType="HubSection">
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="HubSection">
                <Grid Background="WhiteSmoke">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="80"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Grid.RenderTransform>
                        <CompositeTransform x:Name="WrappingTransform"/>
                    </Grid.RenderTransform>
                    <Viewbox HorizontalAlignment="Center" Margin="0">
                        <Image Source="ms-appx:///Assets/Logos/Logo.png" Stretch="Fill"/>
                    </Viewbox>
                    <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0" Grid.Row="1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And I have a HubSection that uses this style. How to programatically access this resource and replace the

<Viewbox HorizontalAlignment="Center" Margin="0">
    <Image Source="ms-appx:///Assets/Logos/Logo.png" Stretch="Fill"/>
</Viewbox>

with some other image?


Solution

  • That's a dirty hack, but since you have only one property to replace, you can take advantage of the Tag property to store your image url:

    <Style x:Key="MainMenuHubSectionStyle2" TargetType="HubSection">
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="HubSection">
                    <Grid Background="WhiteSmoke">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="80"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Grid.RenderTransform>
                            <CompositeTransform x:Name="WrappingTransform"/>
                        </Grid.RenderTransform>
                        <Viewbox HorizontalAlignment="Center" Margin="0">
                            <Image Source="{TemplateBinding Tag}" Stretch="Fill"/>
                        </Viewbox>
                        <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0" Grid.Row="1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    Then you can use it like this:

    <HubSection Tag="ms-appx:///Assets/Logos/Logo.png">
    </HubSection>
    

    Otherwise, you probably would have to make your own type, inheriting from HubSection and adding the necessary properties.

    Alternatively, you could use good ol' databinding, as suggested by RenDishen. For instance:

    <Style x:Key="MainMenuHubSectionStyle2" TargetType="HubSection">
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="HubSection">
                    <Grid Background="WhiteSmoke">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="80"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Grid.RenderTransform>
                            <CompositeTransform x:Name="WrappingTransform"/>
                        </Grid.RenderTransform>
                        <Viewbox HorizontalAlignment="Center" Margin="0">
                            <Image Source="{Binding Path=Logo}" Stretch="Fill"/>
                        </Viewbox>
                        <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0" Grid.Row="1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    Then you would have to assign to the DataContext property of your HubSection an object that has a Logo property, and fill it accordingly.