试图模拟图标 属性

Trying to emulate Icon property

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

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

我正在尝试添加一个图标 属性,类似于 AppBarButton 控件的图标 属性,允许使用文本而不是 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中使用它?

问题出在您对图标依赖项的定义中 属性。您需要在 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;
}

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

  • XAML处理器根本不使用Icon属性,它直接访问IconProperty依赖属性来获取和设置它。
  • 如果在代码中设置 属性,则调用 Icon 属性 的 setter,这只是依赖项 [=35] 的便利包装=],所以你不必调用 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;
    }
}