views:

135

answers:

2

Hello All! I am fairly new to WPF and am probably missing something simple here. If I have 3 controls, only the last control will show the OriginalImage that I specify.

Any help would be most appreciated. Thanks Ryan

Main Window

<Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="200*"/>
            <RowDefinition Height="60" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="85" />
            <ColumnDefinition Width="85" />
            <ColumnDefinition Width="85" />
            <ColumnDefinition Width="85" />
            <ColumnDefinition Width="300" />
        </Grid.ColumnDefinitions>

            <Grid Grid.Row="1">
                <but:ListButton OriginalImage="/CustomItemsPanel;component/ListBox/Images/add.png"
                            DisableImage="/CustomItemsPanel;component/ListBox/Images/addunselect.png"

            />
        </Grid  >
        <Grid Grid.Row="1" Grid.Column="1"  >
            <but:ListButton OriginalImage="/CustomItemsPanel;component/ListBox/Images/add.png"
                            DisableImage="/CustomItemsPanel;component/ListBox/Images/addunselect.png"

            />
        </Grid  >
        <Grid Grid.Row="1" Grid.Column="2"  >
            <but:ListButton OriginalImage="/CustomItemsPanel;component/ListBox/Images/add.png"
                            DisableImage="/CustomItemsPanel;component/ListBox/Images/addunselect.png"

            />
        </Grid>
</Grid>

Control XAML

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomItemsPanel.ListButton">

<LinearGradientBrush x:Key="ButtonBackground"  EndPoint="0.5,1" StartPoint="0.5,0">
    <LinearGradientBrush.GradientStops>
        <GradientStop Color="#FF0E3D70"/>
        <GradientStop Color="#FF001832" Offset="1"/>
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundMouseOver"  EndPoint="0.5,1" StartPoint="0.5,0">
    <LinearGradientBrush.GradientStops>
        <GradientStop Color="#FF1E62A1" />
        <GradientStop Color="#FF0A3C6D" Offset="1"/>
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ButtonBackgroundSelected"  EndPoint="0.5,1" StartPoint="0.5,0">
    <LinearGradientBrush.GradientStops>
        <GradientStop Color="Red" />
        <GradientStop Color="#FF0A2A4C" Offset="1"/>
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

<Style x:Key="Toggle" TargetType="{x:Type Button}">
    <Setter Property="Content">
        <Setter.Value>
            <Image>
                <Image.Style>
                    <Style TargetType="{x:Type Image}">
                        <Setter Property="Source" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ListButton}}, Path=OriginalImage}"/>
                        <Style.Triggers>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Source" Value="{Binding Path=DisableImage, RelativeSource={RelativeSource TemplatedParent}}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Image.Style>
            </Image>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Cursor="Hand">
                        <Border Name="back" Margin="0,1,0,0" Background="{StaticResource ButtonBackground}">
                        <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" x:Name="content" />

                    </Border>
                        <Border BorderThickness="1" BorderBrush="#FF004F92">
                            <Border BorderThickness="0,0,1,0" BorderBrush="#FF101D29" />
                        </Border>
                    </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True" >
                        <Setter TargetName="back" Property="Background" Value="{StaticResource ButtonBackgroundMouseOver}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type local:ListButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ListButton}">
                <Button Style="{StaticResource Toggle}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

</ResourceDictionary>

Control Code Behind

public class ListButton :  Control
{
    public static readonly DependencyProperty MouseOverImageProperty;  
    public static readonly DependencyProperty OriginalImageProperty;
    public static readonly DependencyProperty DisableImageProperty;  

    static ListButton() {

        DefaultStyleKeyProperty.OverrideMetadata(typeof(ListButton), new FrameworkPropertyMetadata(typeof(ListButton)));

        MouseOverImageProperty = DependencyProperty.Register("MouseOverImage", typeof(ImageSource), typeof(ListButton), new UIPropertyMetadata(null));
        OriginalImageProperty = DependencyProperty.Register("OriginalImage", typeof(ImageSource), typeof(ListButton), new UIPropertyMetadata(null));
        DisableImageProperty = DependencyProperty.Register("DisableImage", typeof(ImageSource), typeof(ListButton), new UIPropertyMetadata(null));  
    }  

    public ImageSource MouseOverImage {  
        get { return (ImageSource)GetValue(MouseOverImageProperty); }  
        set { SetValue(MouseOverImageProperty, value); }  
    }  

    public ImageSource OriginalImage {  
        get { return (ImageSource)GetValue(OriginalImageProperty); }  
        set { SetValue(OriginalImageProperty, value); }  
    }

    public ImageSource DisableImage
    {
        get { return (ImageSource)GetValue(DisableImageProperty); }
        set { SetValue(DisableImageProperty, value); }
    }  
}
A: 

I am going to answer my own question. Bitbonk has a great explanation for what I was doing wrong and how styles work. Thanks!

 <Style x:Key="Toggle" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Cursor="Hand">
                    <Border Name="back" Margin="0,1,0,0" Background="{StaticResource ButtonBackground}">
                        <Image Name="imgBut" Source="{Binding Path=(OriginalImage), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ListButton}}}" />
                    </Border>
                    <Border BorderThickness="1" BorderBrush="#FF004F92">
                        <Border BorderThickness="0,0,1,0" BorderBrush="#FF101D29" />
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True" >
                        <Setter TargetName="back" Property="Background" Value="{StaticResource ButtonBackgroundMouseOver}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False" >
                        <Setter TargetName="imgBut" Property="Source" Value="{Binding Path=(DisableImage), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ListButton}}}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Ryan
A: 

This happened because of your "Toggle" style for the Button. The Image you use there is created only once (because the style is only evaluated once) and the Image can not be added to multiple buttons (in WPF each Visual can only have one parent). So the last Button you apply the style to wins and steals the image from the previous button.

If you want to modify the VisualTree in a style you should do this in a ControlTemplate.

bitbonk
Thanks for clearing that up for me.
Ryan