我想创建一些自定义控件。这是我想要实现的屏幕截图。
每个控件包含两个部分,一个标签(TextBlock)和一个编辑器(UIElement)。标签部分对所有控件都是通用的。我不想在我创建的每个自定义控件中继续定义标签。所以我想到了创建一个基类。这是基础编辑器类。
[TemplatePart(Name = PartLabelName, Type = typeof (TextBlock))]
[TemplatePart(Name = PartEditorName, Type = typeof (ContentPresenter))]
public abstract class Editor : Control
{
protected const string PartLabelName = "PartLabel";
protected const string PartEditorName = "PartEditor";
public static readonly DependencyProperty LabelStyleProperty = DependencyProperty.Register(
"LabelStyle", typeof (Style), typeof (Editor), new PropertyMetadata(default(Style)));
public static readonly DependencyProperty LabelHeightProperty = DependencyProperty.Register(
"LabelHeight", typeof (double), typeof (Editor), new PropertyMetadata(default(double)));
public static readonly DependencyProperty LabelWidthProperty = DependencyProperty.Register(
"LabelWidth", typeof (double), typeof (Editor), new PropertyMetadata(default(double)));
public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(
"Label", typeof (string), typeof (Editor), new PropertyMetadata(default(string)));
public static readonly DependencyProperty EditorControlProperty = DependencyProperty.Register(
"EditorControl", typeof (FrameworkElement), typeof (Editor), new PropertyMetadata(default(FrameworkElement)));
public static readonly DependencyProperty EditorWidthProperty = DependencyProperty.Register(
"EditorWidth", typeof (double), typeof (Editor), new PropertyMetadata(default(double)));
public static readonly DependencyProperty EditorHeightProperty = DependencyProperty.Register(
"EditorHeight", typeof (double), typeof (Editor), new PropertyMetadata(default(double)));
public static readonly DependencyProperty EditorStyleProperty = DependencyProperty.Register(
"EditorStyle", typeof (Style), typeof (Editor), new PropertyMetadata(default(Style)));
public static readonly DependencyProperty LabelColorProperty = DependencyProperty.Register(
"LabelColor", typeof (Brush), typeof (Editor), new PropertyMetadata(default(Brush)));
private ContentPresenter _partEditorControl;
private TextBlock _partLabel;
protected Editor()
{
DefaultStyleKey = typeof (Editor);
}
public Brush LabelColor
{
get { return (Brush) GetValue(LabelColorProperty); }
set { SetValue(LabelColorProperty, value); }
}
public Style EditorStyle
{
get { return (Style) GetValue(EditorStyleProperty); }
set { SetValue(EditorStyleProperty, value); }
}
public double EditorHeight
{
get { return (double) GetValue(EditorHeightProperty); }
set { SetValue(EditorHeightProperty, value); }
}
public double EditorWidth
{
get { return (double) GetValue(EditorWidthProperty); }
set { SetValue(EditorWidthProperty, value); }
}
public Style LabelStyle
{
get { return (Style) GetValue(LabelStyleProperty); }
set { SetValue(LabelStyleProperty, value); }
}
public double LabelHeight
{
get { return (double) GetValue(LabelHeightProperty); }
set { SetValue(LabelHeightProperty, value); }
}
public double LabelWidth
{
get { return (double) GetValue(LabelWidthProperty); }
set { SetValue(LabelWidthProperty, value); }
}
public FrameworkElement EditorControl
{
get { return (FrameworkElement) GetValue(EditorControlProperty); }
set { SetValue(EditorControlProperty, value); }
}
public string Label
{
get { return (string) GetValue(LabelProperty); }
set { SetValue(LabelProperty, value); }
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_partLabel = GetTemplateChild(PartLabelName) as TextBlock;
_partEditorControl = GetTemplateChild(PartEditorName) as ContentPresenter;
if (_partLabel == null || _partEditorControl == null)
{
throw new NullReferenceException("Template parts are not available");
}
}
以下是基础编辑器的样式。
<Style TargetType="local:Editor">
<Setter Property="LabelWidth" Value="200" />
<Setter Property="LabelHeight" Value="25" />
<Setter Property="EditorHeight" Value="25" />
<Setter Property="EditorWidth" Value="200" />
<Setter Property="LabelColor" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Editor">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="PartLabel"
Text="{TemplateBinding Label}"
Width="{TemplateBinding LabelWidth}"
Height="{TemplateBinding LabelHeight}"
Style="{TemplateBinding LabelStyle}"
Foreground="{TemplateBinding LabelColor}"
VerticalAlignment="Center" />
<ContentPresenter Grid.Column="1"
x:Name="PartEditor"
Height="{TemplateBinding EditorHeight}"
Width="{TemplateBinding EditorWidth}"
Style="{TemplateBinding EditorStyle}"
Content="{TemplateBinding EditorControl}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
所以我创建了第一个扩展编辑器类的自定义控件。
[TemplatePart(Name = PartLabelName, Type = typeof (TextBlock))]
[TemplatePart(Name = PartEditorName, Type = typeof (ContentPresenter))]
public class NumericUpDownEditor : Editor
{
private ContentPresenter _partEditorControl;
private TextBlock _partLabel;
public NumericUpDownEditor()
{
DefaultStyleKey = typeof (NumericUpDownEditor);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_partLabel = GetTemplateChild(PartLabelName) as TextBlock;
_partEditorControl = GetTemplateChild(PartEditorName) as ContentPresenter;
if (_partLabel == null || _partEditorControl == null)
{
throw new NullReferenceException("Template parts are not available");
}
}
}
默认样式
<Style TargetType="local:NumericUpDownEditor">
<Setter Property="EditorControl">
<Setter.Value>
<toolkit:NumericUpDown />
</Setter.Value>
</Setter>
</Style>
当我在用户控件中使用此NumericEditor时,没有显示任何内容。
<StackPanel x:Name="LayoutRoot" Orientation="Vertical">
<customControls:NumericUpDownEditor Label="Numeric Up" />
</StackPanel>
我只想在我创建的每个自定义控件中设置编辑器UIElement。 我还需要在样式中为NumericEditor定义模板吗?或者我还做错了什么?
谢谢
答案 0 :(得分:0)
发现错误。我将从子类控件中删除默认样式。通过这个answer发现我要在ContentTemplate (DataTemplate)
而不是Content
修改后的编辑器样式和类代码
public static readonly DependencyProperty EditorControlTemplateProperty = DependencyProperty.Register(
"EditorControlTemplate", typeof (DataTemplate), typeof (Editor), new PropertyMetadata(default(DataTemplate)));
<ContentPresenter Grid.Column="1" x:Name="PartEditor"
Height="{TemplateBinding EditorHeight}"
Width="{TemplateBinding EditorWidth}"
Style="{TemplateBinding EditorStyle}"
Content="{TemplateBinding EditorControl}"
ContentTemplate="{TemplateBinding EditorControlTemplate}" />
修改后的子类编辑器
[TemplatePart(Name = PartLabelName, Type = typeof (TextBlock))]
[TemplatePart(Name = PartEditorName, Type = typeof (ContentPresenter))]
public class NumericUpDownEditor : Editor
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof (double), typeof (NumericUpDownEditor), new PropertyMetadata(default(double)));
private ContentPresenter _partEditorControl;
private TextBlock _partLabel;
public double Value
{
get { return (double) GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_partLabel = GetTemplateChild(PartLabelName) as TextBlock;
_partEditorControl = GetTemplateChild(PartEditorName) as ContentPresenter;
if (_partLabel == null || _partEditorControl == null)
{
throw new NullReferenceException("Template parts are not available");
}
}
}
这是分类控制的风格
<Style TargetType="local:NumericUpDownEditor">
<Setter Property="EditorControlTemplate">
<Setter.Value>
<DataTemplate>
<toolkit:NumericUpDown
Value="{Binding RelativeSource={RelativeSource AncestorType=local:NumericUpDownEditor}, Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>