子类一个silverlight模板控件

时间:2015-02-28 20:32:47

标签: c# wpf silverlight controls custom-controls

我想创建一些自定义控件。这是我想要实现的屏幕截图。

Editor Screenshot

每个控件包含两个部分,一个标签(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定义模板吗?或者我还做错了什么?

谢谢

1 个答案:

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