Search code examples
c#wpfvisual-studio-2012wpf-controls

Change predefined style inside a control in xaml


I have the following style in App.xaml:

        <Style TargetType="{x:Type Button}">

            <Style.Resources>
                <DataTemplate x:Key="Unpressed">
                    <Image Stretch="Uniform"  Source="Img/button1.png"/>
                </DataTemplate>
                <DataTemplate x:Key="Pressed">
                    <Image Stretch="Uniform" Source="Img/button1_press.png"/>
                </DataTemplate>
            </Style.Resources>

            <Setter Property="ContentTemplate" Value="{StaticResource Unpressed}"/>

            <Style.Triggers>
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="ContentTemplate" Value="{StaticResource Pressed}"/>
                </Trigger>
            </Style.Triggers>

        </Style>

I want to change the data template from my button, something like this:

                    <Button x:Name="Button2">

                    <Style>
                        <Style.Resources>
                            <DataTemplate x:Key="Unpressed">
                                <Image Stretch="Uniform" Source="../Img/button2.png"/>
                            </DataTemplate>
                            <DataTemplate x:Key="Pressed">
                                <Image Stretch="Uniform" Source="../Img/button2_press.png"/>
                            </DataTemplate>
                        </Style.Resources>
                    </Style>

                </Button>

So basically, all my buttons have the same style but each button have an unique image, I need to change the DataTemplate of the style individually for each button


Solution

  • This is my proposed solution:

    For the style:

    <Application.Resources>
    
        <local:ImgToDisplayConverter x:Key="ImgToDisplayConverter"/>
        <local:ImgPressedToDisplayConverter x:Key="ImgPressedToDisplayConverter"/>
    
        <Style TargetType="Image" x:Key="PressedButtonImageStyle">
            <Setter Property="Source">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource ImgToDisplayConverter}">
                        <Binding Path="Tag" RelativeSource="{RelativeSource AncestorType=Button}"/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource AncestorType=Button}}" Value="true">
                    <Setter Property="Source">
                        <Setter.Value>
                            <MultiBinding Converter="{StaticResource ImgPressedToDisplayConverter}">
                                <Binding Path="Tag" RelativeSource="{RelativeSource AncestorType=Button}"/>
                            </MultiBinding>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    
    </Application.Resources>
    

    For the Control:

        <Button Tag="button1"  Width="100" Height="100" HorizontalAlignment="Left">
            <ContentControl>
                <Image Stretch="Uniform" Style="{StaticResource PressedButtonImageStyle}" IsHitTestVisible="False"/>
            </ContentControl>
        </Button>
    

    The Converters:

     class ImgToDisplayConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            string image = values[0].ToString();
            string resourceName = String.Format("pack://application:,,,/{0}.png", image);
    
            return new BitmapImage(new Uri(resourceName));
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    
    class ImgPressedToDisplayConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            string image = values[0].ToString();
            string resourceName = String.Format("pack://application:,,,/{0}_pressed.png", image);
    
            return new BitmapImage(new Uri(resourceName));
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    You can change the code depending on your needs.