0

我正在尝试创建一个带有图标的“DropDownButton”,并且我希望能够通过附加属性设置图标源(我发现这是(唯一的?)方法)。但由于某种原因,我尝试的一切都失败了,我能得到的最好的结果是一个空的 Image 容器。

我认为这看起来不错,但现在我收到了这些错误:

The local property "Image" can only be applied to types that are derived from "IconButton".
The attachable property 'Image' was not found in type 'IconButton'.
The attached property 'IconButton.Image' is not defined on 'Button' or one of its base classes.

我可能完全错了(我已经尝试和编辑了大约 2 个小时),但我只知道必须有一种方法可以做到这一点。

下面提供了相关代码,如果有人能指出我正确的方向,那就太棒了!

编辑:更新的代码,仍然遇到问题

现在我在调试日志中收到此错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'Image' property not found on 'object' ''ContentPresenter' (Name='')'. BindingExpression:Path=Image; DataItem='ContentPresenter' (Name=''); target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource')

ImageButton.cs(谢谢 Viv):

class ImageButton : Button
{
    public static readonly DependencyProperty ImageProperty =
        DependencyProperty.Register("Image", typeof(ImageSource), typeof(ImageButton),
        new FrameworkPropertyMetadata(null,
            FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender));

    public ImageSource Image
    {
        get { return (ImageSource)GetValue(ImageProperty); }
        set { SetValue(ImageProperty, value); }
    }
}

图像按钮样式:

<Style TargetType="{x:Type Controls:ImageButton}" x:Key="FormIconDropDownButton">
    <Setter Property="Margin" Value="5" />
    <Setter Property="Padding" Value="10,5,4,5" />
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate DataType="{x:Type Controls:ImageButton}">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>

                    <Image Style="{StaticResource FormButtonIcon-Small}"
                           Source="{Binding Image, RelativeSource={RelativeSource TemplatedParent}}"/>

                    <TextBlock Grid.Column="1"
                                Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"
                               VerticalAlignment="Center"
                               Margin="0,0,9,0"/>

                    <Path Grid.Column="2"
                          Fill="Black" 
                          Data="M 0 0 L 3.5 4 L 7 0 Z"
                          VerticalAlignment="Center"/>
                </Grid>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

在窗口 xaml 中:

<Controls:ImageButton Content="Hello"
                              Style="{StaticResource FormIconDropDownButton}"
                              Image="{StaticResource Icon-Small-Locations}" />
4

4 回答 4

3

您只是在 xaml 中使用了错误的控件类型。您仍在使用基类而不是派生类。

此外,您声明的是依赖属性而不是附加属性。

附加属性注册于DependencyProperty.RegisterAttached(...)

现在,您需要IconButton在 xaml 中定义类的位置添加命名空间,例如

xmlns:local="clr-namespace:Mynamespace"

然后切换出现

{x:Type Button}{x:Type local:IconButton}

<Button ...> to <local:IconButton ...>

我不会推荐这个 tbh 的附加属性。当附加属性不应该只是我的意见时,它们会被过度使用。

检查此线程以了解 DP 和 AP 使用之间的一些差异。在这种情况下,它是一个Button显示Image. 使其独特而不是同质化批次。

更新:

使用普通 DP的派生类(ImageButton下载链接。Button

于 2013-06-18T13:28:59.583 回答
1

除了您没有声明附加属性外,一切看起来都是正确的。相反,您刚刚DependencyProperty在您的IconButton类上声明了一个法线,然后仅对设置IconButton或从它派生的类有效。附加属性的声明(可以在任何类型上设置)使用不同的注册调用,并且还使用 get/set 方法而不是包装器属性:

    public static readonly DependencyProperty ImageProperty =
        DependencyProperty.RegisterAttached(
        "Image",
        typeof(ImageSource),
        typeof(IconButton),
        new FrameworkPropertyMetadata(null,
            FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender));

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

    public static void SetImage(DependencyObject target, ImageSource value)
    {
        target.SetValue(ImageProperty, value);
    }
于 2013-06-18T13:43:41.713 回答
1

这是我扩展基类的示例,在样式和视图中使用依赖属性。有关更多详细信息,请写在这篇文章中。

public class ItemsList : ListView {
      public static readonly DependencyProperty ItemIconProperty = DependencyProperty.Register("ItemIcon", typeof(ImageSource), typeof(ItemsList));
      public ImageSource ItemIcon {
         get { return (ImageSource)GetValue(ItemIconProperty); }
         set { SetValue(ItemIconProperty, value); }
      }  

      public static readonly DependencyProperty DoubleClickCommandProperty = DependencyProperty.Register("DoubleClickCommand", typeof(ICommand), typeof(ItemsList));
      public ControlTemplate DoubleClickCommand {
         get { return (ControlTemplate)GetValue(DoubleClickCommandProperty); }
         set { SetValue(DoubleClickCommandProperty, value); }
      }
}

/扩展 ItemList 的样式,其中声明了 'ItemIcon' DependencyProperty /

<Style x:Key="BaseDataSourcesWindowListMenuStyle" TargetType="Controls:ItemsList">    
    <Setter Property="ItemIcon" Value="/Presentation.Shared;component/Resources/Images/data_yellow.png" />    
  </Style>

  <Style x:Key="DataSourcesListMenuStyle" TargetType="Controls:ItemsList"
         BasedOn="{StaticResource BaseDataSourcesWindowListMenuStyle}">    
    <Setter Property="DoubleClickCommand" Value="{Binding Path=VmCommands.EditDataSourceDBCommand}" />
  </Style>

/我如何使用“ItemIcon” DependencyProperty ON VIEW /

<Controls:ItemsList Grid.Column="0" Grid.Row="1" Margin="8" ItemsSource="{Binding DataSourceDbs}"
                        Style="{DynamicResource DataSourcesListMenuStyle}"
                        SelectedItem="{Binding SelectedDataSourceDB, Mode=TwoWay}" />
于 2013-06-18T13:48:23.530 回答
0

首先,我认为这是您在那里声明的依赖属性,它属于 IconButton 自定义控件,您正试图在 Button 控件上使用它。

请参阅http://msdn.microsoft.com/en-us/library/ms749011.aspx以获取有关如何声明附加属性并将该属性分配给 Button 类而不是 IconButton 的参考,因为您没有使用该自定义控件在上面的代码中。

于 2013-06-18T13:16:03.703 回答