试图模拟 Icon 属性

Posted

技术标签:

【中文标题】试图模拟 Icon 属性【英文标题】:Trying to emulate Icon property 【发布时间】:2021-05-08 04:46:51 【问题描述】:

我正在开发一个(简单的)用户控件,它显示图像和文本并发布它们的一些属性。

<UserControl.Resources>
    <BitmapImage x:Key="defaultImg" 
                 UriSource="/mcWpfLibrary;component/Assets/TagBlue.png"/>
    <Thickness x:Key="defaultTxtMargin" 
                Left="5" Top="0" Right="0" Bottom="0"/>
</UserControl.Resources>

<StackPanel Orientation="Horizontal" 
            Background="Transparent">
    <Image Width="Binding Path=ImgWidth, ElementName=imageLabel, FallbackValue=24"
           Height="Binding Path=ImgWidth, ElementName=imageLabel, FallbackValue=24"
           Source="Binding Path=ImgSource, ElementName=imageLabel, FallbackValue=StaticResource defaultImg"
           VerticalAlignment="Center" 
           HorizontalAlignment="Left"
    />
    <TextBlock VerticalAlignment="Center"
        Text="Binding Path=LabelText, ElementName=imageLabel, FallbackValue=Demo text"
        FontSize="Binding Path=LabelFontSize, ElementName=imageLabel, FallbackValue=22"
        FontFamily="Binding Path=LabelFontFamily, ElementName=imageLabel, FallbackValue=Segoe UI"
        Foreground="Binding Path=LabelForeground, ElementName=imageLabel, FallbackValue=White"
        Margin="Binding Path=LabelMargin, ElementName=imageLabel, FallbackValue=StaticResource defaultTxtMargin"
        Style="Binding Path=LabelStyle, ElementName=imageLabel"
        TextTrimming="CharacterEllipsis"
        />
</StackPanel>

我正在尝试添加一个 Icon 属性,类似于 AppBarButton 控件的 Icon 属性,它允许使用文本而不是 URI 分配一些库存图像。

/// <summary>
/// Image Source property
/// </summary>
public ImageSource ImgSource

    get  return (ImageSource)GetValue(ImageSourceProperty); 
    set  SetValue(ImageSourceProperty, value); 


public static readonly DependencyProperty ImageSourceProperty =
    DependencyProperty.Register("ImgSource", typeof(ImageSource), typeof(LabelImg));

/// <summary>
/// Icon property
/// </summary>
public string Icon

    get  return (string)GetValue(IconProperty); 
    set 
     
        SetValue(IconProperty, value); 

        switch (value)
        
            case "Document":
                ImgSource = new BitmapImage(new Uri("/mcWpfLibrary;component/Assets/AddDocumentBlue.png", UriKind.Relative));
                break;
            case "Bullets":
                ImgSource = new BitmapImage(new Uri("/mcWpfLibrary;component/Assets/BulletsBlue.png", UriKind.Relative));
                break;
            case "Tag":
                ImgSource = new BitmapImage(new Uri("/mcWpfLibrary;component/Assets/TagBlue.png", UriKind.Relative));
                break;
        
    


public static readonly DependencyProperty IconProperty =
    DependencyProperty.Register("Icon", typeof(string), typeof(LabelImg), new PropertyMetadata(""));

如果我使用 XAML 分配一些值,它将不起作用:

<jm:LabelImg x:Name="Btn"
             LabelText="hello world"
             Icon="Bullets"/>

但如果我在代码隐藏中分配一些值,它会正常工作:

private void BtnDoc_Click(object sender, RoutedEventArgs e)

    Btn.Icon = "Document";

有没有办法在 XAML 中使用它?

【问题讨论】:

【参考方案1】:

问题在于如何在 XAML 和代码中访问依赖属性。

XAML 处理器根本不使用Icon 属性,它直接访问IconProperty 依赖属性来获取和设置它。 如果你在代码中设置属性,你调用Icon属性的setter,这只是一个对依赖属性的方便包装,所以你不必调用GetValueSetValue并且它不应超过,因为您在问题中描述的原因是 XAML 和代码中的行为不一致。

为了解决这个问题,你必须在你的依赖属性声明中注册一个property changed callback 并将代码从Icon 属性移到那里。每次属性更改时都会调用回调,因此设置Icon属性或其依赖属性的行为相同。

/// <summary>
/// Icon property
/// </summary>
public string Icon

    get  return (string)GetValue(IconProperty); 
    set  SetValue(IconProperty, value); 



public static readonly DependencyProperty IconProperty =
    DependencyProperty.Register("Icon", 
                                typeof(string), 
                                typeof(LabelImg),
                                new FrameworkPropertyMetadata(null,
                                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                    new PropertyChangedCallback(OnIconChanged)));


private static void OnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

    var labelImg = (LabelImg)d;
    var value = (string)e.NewValue;

    switch (value)
    
        case "Document":
            labelImg.ImgSource = new BitmapImage(new Uri("/mcWpfLibrary;component/Assets/AddDocumentBlue.png", UriKind.Relative));
            break;
        case "Bullets":
            labelImg.ImgSource = new BitmapImage(new Uri("/mcWpfLibrary;component/Assets/BulletsBlue.png", UriKind.Relative));
            break;
        case "Tag":
            labelImg.ImgSource = new BitmapImage(new Uri("/mcWpfLibrary;component/Assets/TagBlue.png", UriKind.Relative));
            break;
    

【讨论】:

谢谢,我已经编辑了答案以修复一些错误。 @McNets 感谢编辑,看来我不是偶然发布了最终版本。【参考方案2】:

问题在于您对 Icon 依赖项属性的定义。您需要在 PropertyMetadata 中定义 PropertyChangedCallback。否则,它将不知道如何处理从 XAML 接收到的初始值。

快速修复:

public static readonly DependencyProperty IconProperty =
    DependencyProperty.Register("Icon", typeof(string), typeof(UserControl1), new PropertyMetadata(OnPropertyChanged));

private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

    var control = d as <Insert-The-Name-Of-Your-UserControl>;
    control.Icon = e.NewValue as string;

【讨论】:

以上是关于试图模拟 Icon 属性的主要内容,如果未能解决你的问题,请参考以下文章

button按钮(icon)

练习-为网页添加icon图标;为网页添加关键字/作者;超链接;input的type属性有哪些常用属性值-form表单

C#界面里Form.Icon 属性的使用

C#界面里Form.Icon 属性的使用

Window 中的 Icon 属性使 Windows XP SP2 中的应用程序崩溃

apple-touch-icon-precomposed