基于网格或嵌套网格的WPF自定义控件?

时间:2017-03-06 10:03:48

标签: c# wpf custom-controls

我正在学习WPF,但我有很多Windows窗体背景。我想转换一个WinForms自定义控件,我在其中放置了一个标签和一个文本框(制作一个TextField),其中一个属性允许设置分配给标签的宽度百分比。

现在,在WPF中,我有点迷失了。我应该创建一个从网格继承并公开(如何?)列定义属性的自定义控件,还是应该创建一个自定义控件,它将包含"包含"一个网格,并公开两个属性" LabelWidth"和" ContentWidth",并将两个列定义绑定到这些属性? (认为​​这些属性包含1 *和3 *)。

有人能告诉我一个这样的建筑的例子,有一个地方可以开始吗?

2 个答案:

答案 0 :(得分:2)

您可以使用两个依赖项属性创建UserControl

请参阅以下示例代码。

<强> MyUserControl.xaml:

<UserControl x:Class="WpfApplication3.MyUserControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WpfApplication3"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="{Binding LabelWidth, RelativeSource={RelativeSource AncestorType=UserControl}}" />
            <ColumnDefinition Width="{Binding ContentWidth, RelativeSource={RelativeSource AncestorType=UserControl}}" />
        </Grid.ColumnDefinitions>
        <TextBlock Text="..." />
        <TextBox Grid.Column="1" />
    </Grid>
</UserControl>

<强> MyUserControl.xaml.cs:

public partial class MyUserControl:UserControl     {         public MyUserControl()         {             的InitializeComponent();         }

    public static readonly DependencyProperty LabelWidthProperty =
         DependencyProperty.Register("LabelWidth", typeof(System.Windows.GridLength),
         typeof(MyUserControl));

    public System.Windows.GridLength LabelWidth
    {
        get { return (System.Windows.GridLength)GetValue(LabelWidthProperty); }
        set { SetValue(LabelWidthProperty, value); }
    }

    public static readonly DependencyProperty ContentWidthProperty =
        DependencyProperty.Register("ContentWidth", typeof(System.Windows.GridLength),
            typeof(MyUserControl));

    public System.Windows.GridLength ContentWidth
    {
        get { return (System.Windows.GridLength)GetValue(ContentWidthProperty); }
        set { SetValue(ContentWidthProperty, value); }
    }
}

样本使用:

<local:MyUserControl LabelWidth="1*" ContentWidth="5*" />

依赖项属性概述: https://msdn.microsoft.com/en-us/library/ms752914(v=vs.110).aspx

答案 1 :(得分:0)

我认为通过了解mm8的代码,特别是RelativeSource={RelativeSource AncestorType=UserControl},我设法实现了我想要的目标:

添加了自定义控件。 FieldText.cs:

public class FieldText : Control
{
    static FieldText()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(FieldText), new FrameworkPropertyMetadata(typeof(FieldText)));
    }

    public FieldText()
    {
    }

    public static readonly DependencyProperty LabelLengthProperty =
        DependencyProperty.Register("LabelLength", typeof(GridLength),
        typeof(FieldText), new UIPropertyMetadata(new GridLength(25, GridUnitType.Star)));

    public virtual GridLength LabelLength
    {
        get { return (GridLength)GetValue(LabelLengthProperty); }
        set { SetValue(LabelLengthProperty, value); }
    }

    public static readonly DependencyProperty ContentLengthProperty =
        DependencyProperty.Register("ContentLength", typeof(GridLength),
        typeof(FieldText), new UIPropertyMetadata(new GridLength(75, GridUnitType.Star)));

    public virtual GridLength ContentLength
    {
        get { return (GridLength)GetValue(ContentLengthProperty); }
        set { SetValue(ContentLengthProperty, value); }
    }
}

Generic.xaml:

<Style TargetType="{x:Type controls:FieldText}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:FieldText}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid x:Name="grd" Margin="3px">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="{Binding Path=LabelLength, RelativeSource={RelativeSource AncestorType=Control}}" />
                            <ColumnDefinition Width="{Binding Path=ContentLength, RelativeSource={RelativeSource AncestorType=Control}}" />
                        </Grid.ColumnDefinitions>
                        <Label x:Name="label" Grid.Column="0" Content="Field:" />
                        <TextBox x:Name="textbox" Grid.Column="1" MaxLines="1" TextWrapping="NoWrap" />
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

样本使用:

<controls:FieldText x:Name="fld1" LabelLength="25*" ContentLength="75*" />