与 AppBarButton 中的图标 属性 相似的自定义控件
Custom Control with Icon Property alike in AppBarButton
在 UWP 中,AppBarButton 有一个 Icon 属性。您可以在其中放置任何类型的 IconElement,或者您只需键入一个符号名称,intellisence 就会显示可用符号列表。
我想制作一个控件,它也将具有一个 IconElement,其行为方式相同(键入符号名称或放置从 IconElement 继承的元素),但我不完全确定我怎样才能实现这样的目标。
TemplatedControl 代码
[ContentProperty(Name = "Label")]
public sealed class CustomIconButton : Control
{
public CustomIconButton() => this.DefaultStyleKey = typeof(CustomIconButton);
public IconElement Icon
{
get { return (IconElement)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(IconElement), typeof(CustomIconButton), new PropertyMetadata(default(IconElement)));
public string Label
{
get { return (string)GetValue(LabelProperty); }
set { SetValue(LabelProperty, value); }
}
public static readonly DependencyProperty LabelProperty =
DependencyProperty.Register("Label", typeof(string), typeof(CustomIconButton), new PropertyMetadata(default(string)));
}
我应该用 Icon属性 getter 做点什么,还是我应该覆盖 OnApplyTemplate() 并在那里做点什么?
我不确定它是某些功能还是更复杂的构建。
创建模板控件时,会自动生成一个xaml文件存放新的控件样式和模板(Themes文件夹->Generic.xaml), 你需要添加控件来显示你的图标和文字,你设置的IconProperty和LabelProperty的值最终会传递给控件模板中控件对应的属性。
为了实现,我们通常使用TemplateBinding。基于AppBarButton的默认样式,它使用ContentPresenter绑定其Icon的值属性,我们也可以这样做。例如:
Generic.xaml:
<Style TargetType="local:CustomIconButton" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomIconButton">
<StackPanel>
<Viewbox x:Name="ContentViewbox" AutomationProperties.AccessibilityView="Raw" HorizontalAlignment="Stretch" Height="{ThemeResource AppBarButtonContentHeight}" Margin="{ThemeResource AppBarButtonContentViewboxCollapsedMargin}">
<ContentPresenter x:Name="Content" Content="{TemplateBinding Icon}" Foreground="{TemplateBinding Foreground}"/>
</Viewbox>
<TextBlock Text="{TemplateBinding Label}"></TextBlock>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
要使用此自定义控件:
MainPage.xaml:
<local:CustomIconButton Icon="Accept" Width="30">hello</local:CustomIconButton>
在 UWP 中,AppBarButton 有一个 Icon 属性。您可以在其中放置任何类型的 IconElement,或者您只需键入一个符号名称,intellisence 就会显示可用符号列表。
我想制作一个控件,它也将具有一个 IconElement,其行为方式相同(键入符号名称或放置从 IconElement 继承的元素),但我不完全确定我怎样才能实现这样的目标。
TemplatedControl 代码
[ContentProperty(Name = "Label")]
public sealed class CustomIconButton : Control
{
public CustomIconButton() => this.DefaultStyleKey = typeof(CustomIconButton);
public IconElement Icon
{
get { return (IconElement)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(IconElement), typeof(CustomIconButton), new PropertyMetadata(default(IconElement)));
public string Label
{
get { return (string)GetValue(LabelProperty); }
set { SetValue(LabelProperty, value); }
}
public static readonly DependencyProperty LabelProperty =
DependencyProperty.Register("Label", typeof(string), typeof(CustomIconButton), new PropertyMetadata(default(string)));
}
我应该用 Icon属性 getter 做点什么,还是我应该覆盖 OnApplyTemplate() 并在那里做点什么?
我不确定它是某些功能还是更复杂的构建。
创建模板控件时,会自动生成一个xaml文件存放新的控件样式和模板(Themes文件夹->Generic.xaml), 你需要添加控件来显示你的图标和文字,你设置的IconProperty和LabelProperty的值最终会传递给控件模板中控件对应的属性。
为了实现,我们通常使用TemplateBinding。基于AppBarButton的默认样式,它使用ContentPresenter绑定其Icon的值属性,我们也可以这样做。例如:
Generic.xaml:
<Style TargetType="local:CustomIconButton" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CustomIconButton">
<StackPanel>
<Viewbox x:Name="ContentViewbox" AutomationProperties.AccessibilityView="Raw" HorizontalAlignment="Stretch" Height="{ThemeResource AppBarButtonContentHeight}" Margin="{ThemeResource AppBarButtonContentViewboxCollapsedMargin}">
<ContentPresenter x:Name="Content" Content="{TemplateBinding Icon}" Foreground="{TemplateBinding Foreground}"/>
</Viewbox>
<TextBlock Text="{TemplateBinding Label}"></TextBlock>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
要使用此自定义控件:
MainPage.xaml:
<local:CustomIconButton Icon="Accept" Width="30">hello</local:CustomIconButton>