WPF自定义控件:TemplateBinding到图像

Dav*_*man 7 wpf image wpf-controls controltemplate templatebinding

我正在创建一个WPF自定义控件,一个ButtonImageText.我已经添加了两个依赖属性到控制,ImagePath并且Text,控制模板(在主题\ Generic.xaml)是水平排列的图像和文本的简单堆叠面板.

Text物业工作正常.但由于某些原因,在我的测试项目中的样本图像不,当我使用出现TemplateBindingImagePath依赖属性得到其路径.我已经通过临时替换TemplateBinding自定义控件中的图像路径来测试图像,在这种情况下它会出现.

我希望在这个领域有更多经验的人可以看看并告诉我为什么控制没有按预期工作.谢谢你的帮助.

我的VS 2008解决方案包含一个项目CustomControlDemo.该项目包含一个自定义控件,TaskButton.cs和一个主窗口Window1.xaml,我用它来测试控件.我的测试图像,calendar.png,坐落在该项目的根级资源文件夹,Generic.xaml坐落在一个主题文件夹中,也是在项目的根目录下.

这是我的自定义控件的代码(来自TaskButton.cs):

using System.Windows;
using System.Windows.Controls;

namespace CustomControlDemo
{
    public class TaskButton : RadioButton
    {
        #region Fields

        // Dependency property backing variables
        public static readonly DependencyProperty ImagePathProperty;
        public static readonly DependencyProperty TextProperty;

        #endregion

        #region Constructors

        /// <summary>
        /// Default constructor.
        /// </summary>
        static TaskButton()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TaskButton), new FrameworkPropertyMetadata(typeof(TaskButton)));

            // Initialize ImagePath dependency properties
            ImagePathProperty = DependencyProperty.Register("ImagePath", typeof(string), typeof(TaskButton), new UIPropertyMetadata(null));
            TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(TaskButton), new UIPropertyMetadata(null));
        }

        #endregion

        #region Dependency Property Wrappers

        /// <summary>
        /// The ImagePath dependency property.
        /// </summary>
        public string ImagePath
        {
            get { return (string)GetValue(ImagePathProperty); }
            set { SetValue(ImagePathProperty, value); }
        }

        /// <summary>
        /// The Text dependency property.
        /// </summary>
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        #endregion
    }
}
Run Code Online (Sandbox Code Playgroud)

这是控件模板(来自Generic.xaml):

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


    <Style TargetType="{x:Type local:TaskButton}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:TaskButton}">
                    <StackPanel Height="Auto" Orientation="Horizontal">
                        <Image Source="{TemplateBinding ImagePath}"  Width="24" Height="24" Stretch="Fill"/>
                        <TextBlock Text="{TemplateBinding Text}"  HorizontalAlignment="Left" Foreground="{DynamicResource TaskButtonTextBrush}" FontWeight="Bold"  Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)

最后,这是我用来测试控件的Window1标记:

<Window x:Class="CustomControlDemo.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:customControl="clr-namespace:CustomControlDemo"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <customControl:TaskButton ImagePath="Resources\calendar.png" Text="Calendar" />
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

任何想法为什么图像路径不起作用?再次感谢.

Dav*_*man 10

我将把cwap的答案作为公认的答案,因为它在技术上是正确的.但事实证明,有一种更简单的方法可以解决这个问题.

TemplateBindings不是一流的Binding对象.它们设计为轻量级,因此它们是单向的,并且它们缺少其他Binding对象的某些功能.最值得注意的是,它们不支持与目标相关联的已知类型转换器.参见C#2008中的 MacDonald,Pro WPF,p.872.这就是为什么cwap正确响应我可能需要创建一个类型转换器并在我的自定义按钮的控件模板中专门引用它.

但我不必使用TemplateBinding将控件模板绑定到我的自定义控件的ImagePath属性.我可以使用普通的旧Binding对象.这是我的自定义控件模板的修订标记:

<!-- Task Button Default Control Template-->
<Style TargetType="{x:Type local:TaskButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:TaskButton}">
                <StackPanel Height="Auto" Orientation="Horizontal">
                    <Image Source="{Binding Path=ImagePath, RelativeSource={RelativeSource TemplatedParent}}" Width="24" Height="24" Stretch="Fill" Margin="10,0,0,0" />
                    <TextBlock Text="{TemplateBinding Text}"  HorizontalAlignment="Left" Foreground="{TemplateBinding Foreground}" FontWeight="Bold"  Margin="5,0,10,0" VerticalAlignment="Center" FontSize="12" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)

如果查看模板中的ImageControl,可以看到更改.请注意同一对象中的RelativeSource属性.将此属性设置为= {RelativeSource TemplatedParent}是允许我在TaskButton的Window1实例中输入相对路径并在自定义控件中正确解析的.

因此,我对其他人研究此线程的建议是跳过值转换器,只需从TemplateBinding切换到Image属性的Binding即可.

还要感谢Marco Zhou,他在MSDN WPF论坛中提供了类似问题的答案.


cwa*_*wap 4

图像不将字符串作为源:) 您可以在智能感知中看到这一点。您需要绑定 ImageSource (或使用 IValueConverter 将字符串转换为 ImageSource)

请参阅问题以获取有关如何进行此转换的一些提示。