试图模拟 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,这只是一个对依赖属性的方便包装,所以你不必调用GetValue
和SetValue
并且它不应超过,因为您在问题中描述的原因是 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 属性的主要内容,如果未能解决你的问题,请参考以下文章
练习-为网页添加icon图标;为网页添加关键字/作者;超链接;input的type属性有哪些常用属性值-form表单