在 class 层次结构中用 AttachedProperty 替换 DependencyProperty - 这可能吗?
Replacing DependencyProperty by AttachedProperty in class hierarchy - is that possible?
我希望我的一些 Button
、ToggleButton
和 RadioButton
有一个 Geometry 属性 以便我可以在 ControlTemplates 中使用以避免在分配实例时使用样板代码-这些控件的特定几何形状。
例如,目前我可以这样写:
<my:GeometryButton Geometry="{StaticResource OneGeometry}"/>
<my:GeometryButton Geometry="{StaticResource OtherGeometry}"/>
<!-- ...and inside the Style for GeometryButton: -->
<ContentControl TargetType="{x:Type my:GeometryButton}">
<Border>
<Path Data={TemplateBinding Geometry}/>
</Border>
</ContentControl>
有了这个 GeometryButton class:
public class GeometryButton : Button
{
static GeometryButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(GeometryButton),
new FrameworkPropertyMetadata(typeof(GeometryButton)));
}
public Geometry Geometry
{
get { return (Geometry)GetValue(GeometryProperty); }
set { SetValue(GeometryProperty, value); }
}
public static readonly DependencyProperty GeometryProperty =
DependencyProperty.Register("Geometry",
typeof(Geometry),
typeof(GeometryButton),
new PropertyMetadata(default(Geometry)));
}
问题是,如果我要定义 GeometryToggleButton
和 GeometryRadioButton
classes,我应该在每个 class 中重复 DependencyProperty 代码,这违反了 DRY .
另外,由于 RadioButton 派生自 ToggleButton,后者和 Button 又派生自 ButtonBase,我想我可以利用这一点,但如果我需要分别从每个 class 继承,我不会从继承中受益完全没有。
所以我考虑使用AttachedProperties,但是教程和示例通常会提到DockPanel.Dock
、Grid.Left
或Control.Foreground
这样的示例,暗示存在一些"Parent" ,所以我不确定:
- AttachedProperties 概念首先适用于我的用例吗?
- 如果是,我该如何实施?
创建一个常规附件属性。在您的控件模板中,使用它。
说真的,没有比这更多的了。
例如,我写了一个附件CornerRadius
属性,这样许多不同的控件样式都可以指定一个CornerRadius
,它们将被它们的模板使用。
public static class Attached
{
public static readonly DependencyProperty CornerRadiusProperty
= DependencyProperty.RegisterAttached(
"CornerRadius",
typeof(CornerRadius),
typeof(Attached),
new FrameworkPropertyMetadata(
new CornerRadius(0),
FrameworkPropertyMetadataOptions.AffectsRender
| FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
PropertyChanged)
);
public static CornerRadius GetCornerRadius(DependencyObject uie)
{
return (CornerRadius)uie.GetValue(CornerRadiusProperty);
}
public static void SetCornerRadius(DependencyObject uie, CornerRadius value)
{
uie.SetValue(CornerRadiusProperty, value);
}
}
XAML
N.B. Binding
中(edcorpext:Attached.CornerRadius)
两边的括号很关键,所以它理解字符串是一个不可分割的路径段参考附件属性;否则它会尝试将其解析为 Binding.Source
的 属性 的路径,命中 :
并抛出异常。
<ControlTemplate x:Key="EdCorpButtonTemplate" TargetType="{x:Type Button}">
<Grid>
<Border
x:Name="PART_BackgroundBorder"
CornerRadius="{Binding (edcorpext:Attached.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"
BorderThickness="1.3"
BorderBrush="{StaticResource ControlBorderBrush}"
Background="{StaticResource EdCorpGrayMediumGradientBrush}"
SnapsToDevicePixels="True"
/>
<!-- etc. etc. etc. -->
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="edcorpext:Attached.CornerRadius" Value="{StaticResource ButtonCornerRadius}" />
<Setter Property="Template" Value="{StaticResource EdCorpButtonTemplate}" />
<!-- etc. etc. etc. -->
他们告诉我我们需要 UI 在这个应用程序上看起来 "more modern" 并且由于我们没有真正知道他在做什么的设计师,所以我在东西上放置了不对称的圆角。之前的情况其实差了很多。
我希望我的一些 Button
、ToggleButton
和 RadioButton
有一个 Geometry 属性 以便我可以在 ControlTemplates 中使用以避免在分配实例时使用样板代码-这些控件的特定几何形状。
例如,目前我可以这样写:
<my:GeometryButton Geometry="{StaticResource OneGeometry}"/>
<my:GeometryButton Geometry="{StaticResource OtherGeometry}"/>
<!-- ...and inside the Style for GeometryButton: -->
<ContentControl TargetType="{x:Type my:GeometryButton}">
<Border>
<Path Data={TemplateBinding Geometry}/>
</Border>
</ContentControl>
有了这个 GeometryButton class:
public class GeometryButton : Button
{
static GeometryButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(GeometryButton),
new FrameworkPropertyMetadata(typeof(GeometryButton)));
}
public Geometry Geometry
{
get { return (Geometry)GetValue(GeometryProperty); }
set { SetValue(GeometryProperty, value); }
}
public static readonly DependencyProperty GeometryProperty =
DependencyProperty.Register("Geometry",
typeof(Geometry),
typeof(GeometryButton),
new PropertyMetadata(default(Geometry)));
}
问题是,如果我要定义 GeometryToggleButton
和 GeometryRadioButton
classes,我应该在每个 class 中重复 DependencyProperty 代码,这违反了 DRY .
另外,由于 RadioButton 派生自 ToggleButton,后者和 Button 又派生自 ButtonBase,我想我可以利用这一点,但如果我需要分别从每个 class 继承,我不会从继承中受益完全没有。
所以我考虑使用AttachedProperties,但是教程和示例通常会提到DockPanel.Dock
、Grid.Left
或Control.Foreground
这样的示例,暗示存在一些"Parent" ,所以我不确定:
- AttachedProperties 概念首先适用于我的用例吗?
- 如果是,我该如何实施?
创建一个常规附件属性。在您的控件模板中,使用它。
说真的,没有比这更多的了。
例如,我写了一个附件CornerRadius
属性,这样许多不同的控件样式都可以指定一个CornerRadius
,它们将被它们的模板使用。
public static class Attached
{
public static readonly DependencyProperty CornerRadiusProperty
= DependencyProperty.RegisterAttached(
"CornerRadius",
typeof(CornerRadius),
typeof(Attached),
new FrameworkPropertyMetadata(
new CornerRadius(0),
FrameworkPropertyMetadataOptions.AffectsRender
| FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
PropertyChanged)
);
public static CornerRadius GetCornerRadius(DependencyObject uie)
{
return (CornerRadius)uie.GetValue(CornerRadiusProperty);
}
public static void SetCornerRadius(DependencyObject uie, CornerRadius value)
{
uie.SetValue(CornerRadiusProperty, value);
}
}
XAML
N.B. Binding
中(edcorpext:Attached.CornerRadius)
两边的括号很关键,所以它理解字符串是一个不可分割的路径段参考附件属性;否则它会尝试将其解析为 Binding.Source
的 属性 的路径,命中 :
并抛出异常。
<ControlTemplate x:Key="EdCorpButtonTemplate" TargetType="{x:Type Button}">
<Grid>
<Border
x:Name="PART_BackgroundBorder"
CornerRadius="{Binding (edcorpext:Attached.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"
BorderThickness="1.3"
BorderBrush="{StaticResource ControlBorderBrush}"
Background="{StaticResource EdCorpGrayMediumGradientBrush}"
SnapsToDevicePixels="True"
/>
<!-- etc. etc. etc. -->
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="edcorpext:Attached.CornerRadius" Value="{StaticResource ButtonCornerRadius}" />
<Setter Property="Template" Value="{StaticResource EdCorpButtonTemplate}" />
<!-- etc. etc. etc. -->
他们告诉我我们需要 UI 在这个应用程序上看起来 "more modern" 并且由于我们没有真正知道他在做什么的设计师,所以我在东西上放置了不对称的圆角。之前的情况其实差了很多。