Question

I am trying to develop an application that uses a number of images that are stored in a seperate remote file location. The file-paths to the UI elements are stored within the Application Settings. Although I understand how to access the images from Applications Settings using a MultiBinding and a value converter, I'm not sure how to integrate the Multibinding into the ImageButton ControlTemplate below. Can anyone steer me in the right direction?

<Image.Source>
     <MultiBinding Converter="{StaticResource MyConverter}">
         <Binding Source="{StaticResource Properties.Settings}" Path="Default.pathToInterfaceImages" />
         <Binding Source="ScreenSaver.png"></Binding>
     </MultiBinding>
</Image.Source>

<Button Click="btn_ScreenSaver_Click" Style="{DynamicResource ThreeImageButton}"
               local:ThreeImageButton.Image="C:\Skins\ScreenSaver_UP.png"
               local:ThreeImageButton.MouseOverImage="C:\Skins\ScreenSaver_OVER.png" 
               local:ThreeImageButton.PressedImage="C:\Skins\ScreenSaver_DOWN.png"/>

<Style 
    x:Key="ThreeImageButton"
    TargetType="{x:Type Button}">
    <Setter Property="FontSize" Value="10"/>
    <Setter Property="Height" Value="34"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <StackPanel Orientation="Horizontal" >
                    <Image Name="PART_Image" Source= "{Binding Path=(local:ThreeImageButton.Image), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" />
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Source" Value="{Binding Path=(local:ThreeImageButton.MouseOverImage), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" TargetName="PART_Image"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Source" Value="{Binding Path=(local:ThreeImageButton.PressedImage), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" TargetName="PART_Image"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Source" Value="{Binding Path=(local:ThreeImageButton.Image), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" TargetName="PART_Image"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

public class ThreeImageButton : DependencyObject
{
    // Add three new Dependency Properties to the Button Class to hold the 
    // path to each of the images that are bound to the control, displayed 
    // during normal, mouse-over and pressed states.
    public static readonly DependencyProperty ImageProperty;
    public static readonly DependencyProperty MouseOverImageProperty;
    public static readonly DependencyProperty PressedImageProperty;

    public static ImageSource GetImage(DependencyObject obj)
    { return (ImageSource)obj.GetValue(ImageProperty); }

    public static ImageSource GetMouseOverImage(DependencyObject obj)
    { return (ImageSource)obj.GetValue(MouseOverImageProperty); }

    public static ImageSource GetPressedImage(DependencyObject obj)
    { return (ImageSource)obj.GetValue(PressedImageProperty); }

    public static void SetImage(DependencyObject obj, ImageSource value)
    { obj.SetValue(ImageProperty, value); }

    public static void SetMouseOverImage(DependencyObject obj, ImageSource value)
    { obj.SetValue(MouseOverImageProperty, value); }

    public static void SetPressedImage(DependencyObject obj, ImageSource value)
    { obj.SetValue(PressedImageProperty, value); }

    // Register each property with the control.
    static ThreeImageButton()
    {
        var metadata = new FrameworkPropertyMetadata((ImageSource)null);
        ImageProperty = DependencyProperty.RegisterAttached("Image", typeof(ImageSource), typeof(ThreeImageButton), metadata);
        var metadata1 = new FrameworkPropertyMetadata((ImageSource)null);
        MouseOverImageProperty = DependencyProperty.RegisterAttached("MouseOverImage", typeof(ImageSource), typeof(ThreeImageButton), metadata1);
        var metadata2 = new FrameworkPropertyMetadata((ImageSource)null);
        PressedImageProperty = DependencyProperty.RegisterAttached("PressedImage", typeof(ImageSource), typeof(ThreeImageButton), metadata2);
    }
}
Was it helpful?

Solution

Use XAML property element syntax:

<ControlTemplate TargetType="{x:Type Button}">
  <StackPanel Orientation="Horizontal" >
    <Image>
      <Image.Source>
        <MultiBinding Converter="{StaticResource MyConverter}">
          <Binding Source="{StaticResource Properties.Settings}"
                   Path="Default.pathToInterfaceImages" />
          <Binding Path="(local:ThreeImageButton.Image)"
                   RelativeSource="{RelativeSource TemplatedParent}" />
        </MultiBinding>
      </Image.Source>
    </Image>
  </StackPanel>
</ControlTemplate>

Note this means your attached properties will need to be strings rather than ImageSources, because they are going to be inputs to your path composition converter.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top