【问题标题】:Multibinding File-Paths into a Button ControlTemplate将文件路径多绑定到按钮 ControlTemplate
【发布时间】:2010-03-27 19:15:42
【问题描述】:

我正在尝试开发一个应用程序,该应用程序使用存储在单独的远程文件位置的多个图像。 UI 元素的文件路径存储在应用程序设置中。虽然我了解如何使用 MultiBinding 和值转换器从应用程序设置访问图像,但我不确定如何将 Multibinding 集成到下面的 ImageButton ControlTemplate 中。谁能引导我朝着正确的方向前进?

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

【问题讨论】:

    标签: wpf controltemplate imagebutton multibinding


    【解决方案1】:

    使用 XAML 属性元素语法:

    <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>
    

    请注意,这意味着您的附加属性需要是字符串而不是 ImageSource,因为它们将成为路径合成转换器的输入

    【讨论】:

    • 伊托尔森 - 感谢您的帮助。我相信我按照建议进行了所有修改;但是返回以下错误: System.Windows.Data Error:6: 'TargetDefaultValueConverter' 转换器无法转换值 'interface\btn_fullscreen-off_DOWN.png' (type 'String');如果可用,将使用后备值。绑定表达式:路径=(0);数据项='按钮'(名称='btn_Fullscreen_Off');目标元素是“图像”(名称=“PART_Image”);目标属性是'Source'(类型'ImageSource')IOException:'System.IO.IOException:找不到资源'interface/btn_fullscreen-off_down.png'。有什么想法吗?
    • 好像没有找到文件。路径是否正确?在您的示例中,您指出路径应该是c:\skins` rather than interface`。在调试器中逐步检查您的 IMultiValueConverter。它接收到正确的值吗?它是否返回正确的值?
    • Itowlson - 再次感谢您的建议和帮助。我按照您的建议逐步完成了 IMultiValueConverter 并找到了罪魁祸首。所以绑定是有效的,但是在 IsMouseOver/IsPressed/IsEnabled 期间图像会闪烁。我能问一下您建议为 IsMouseOver/IsPressed/IsEnabled 事件调整代码吗?谢谢。比尔
    • 我的猜测是您的 IMVC 每次都返回新的 ImageSource 实例。所以 WPF 认为结果已经改变并重新加载图像。一个可能的快速解决方法是维护从路径到 ImageSource 实例的字典,以便您可以为相同的路径返回相同的 ImageSource。虽然没有测试过这个。 stackoverflow.com/questions/2530915/… 可能是相关的,尽管它似乎还没有一个好的答案。 (如果我的建议有效,那么也许您可以将其作为答案发布在那里)。
    • Itowlson - 将进行测试并报告。谢谢,我非常感谢您的帮助。比尔
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 2021-03-18
    相关资源
    最近更新 更多