0

我是 WPF 和 Windows 窗体的新手。我需要知道如何定义控件的自定义类(例如标签或文本框...)并定义它的外观并为该控件的任何所需事件编写自定义方法。就像单击时在标签周围放置黑色边框一样。

我需要做所有这些,以便我可以根据需要动态创建该类的尽可能多的实例,确保它们都具有相同的功能和我放入它们的外观。

有没有关于这个的简单教程?

4

2 回答 2

5

您正在寻找的是从已经存在的控件(CustomControl)继承创建一个新控件,您可以将控件添加到该控件(UserControl)中。如果它只是一个控件的自定义类(如标签或文本框),那么我会尝试使用 CustomControl 来解决它

WinForms 和 WPF 的名称相同。我可以提供一些链接,但我认为你最好只是谷歌它,这样你就可以找到最适合你需要的示例/教程。

编辑

好的,所以我会说 - 根据您的背景 - WinForms 更简单一些。但是,如果您制作专业程序,WPF 可能是要走的路。(WinForms 有点老了)

WinForm

至少,这里是一个非常简短的 WinForm CustomControl 示例:

namespace BorderLabelWinForms
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing;

    public class BorderLabel : Label
    {
        private bool _showBorder = false;

        protected override void OnMouseClick(MouseEventArgs e)
        {
            _showBorder = !_showBorder;
            base.OnMouseClick(e);
            this.Refresh();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (_showBorder)
            {
                Pen pen = new Pen(new SolidBrush(Color.Black), 2.0f);
                e.Graphics.DrawRectangle(pen, this.ClientRectangle);
                pen.Dispose();
            }
        }
    }
}

然后你可以从那里开始并扩展它。

WPF

WPF 更复杂,但要创建自定义控件,您可以在项目视图中右键单击项目,然后选择添加 > 新项目。在弹出的对话框中,选择一个自定义控件 (WPF)。现在您将获得一个新的 {choosen name}.cs(在我的示例中为 BorderLable)和一个目录;主题和 Generic.xaml 文件。通用文件是描述如何构建控件的资源。例如这里我在 CustomControl 中添加了一个标签:

通用的.xaml:

    <Style TargetType="{x:Type local:BorderLabel}">
        <Style.Resources>
            <local:ThicknessAndBoolToThicknessConverter x:Key="tabttc" />
        </Style.Resources>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:BorderLabel}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}" >
                        <Border.BorderThickness>
                            <MultiBinding Converter="{StaticResource tabttc}" >
                                <Binding Path="BorderThickness" RelativeSource="{RelativeSource TemplatedParent}" />
                                <Binding Path="ShowBorder" RelativeSource="{RelativeSource TemplatedParent}" />
                            </MultiBinding>
                        </Border.BorderThickness>
                        <Label Content="{TemplateBinding Content}" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

边界标签.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace BorderButton
{
    /// <summary>
    /// Bla. bla bla...
    /// </summary>
    public class BorderLabel : Label
    {
        //DependencyProperty is needed to connect to the XAML
        public bool ShowBorder
        {
            get { return (bool)GetValue(ShowBorderProperty); }
            set { SetValue(ShowBorderProperty, value); }
        }

        public static readonly DependencyProperty ShowBorderProperty =
            DependencyProperty.Register("ShowBorder", typeof(bool), typeof(BorderLabel), new UIPropertyMetadata(false));

        //Override OnMouseUp to catch the "Click". Toggle Border visibility
        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            ShowBorder = !ShowBorder;
        }

        //Contructor (some default created when selecting new CustomControl)
        static BorderLabel()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(BorderLabel), new FrameworkPropertyMetadata(typeof(BorderLabel)));
        }
    }

    //So doing it the WPF way, I wanted to bind the thickness of the border
    //to the selected value of the border, and the ShowBorder dependency property
    public class ThicknessAndBoolToThicknessConverter : IMultiValueConverter
    {

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (values[0] is Thickness && values[1] is bool)
            {
                Thickness t = (Thickness)values[0];
                bool ShowBorder = (bool)values[1];

                if (ShowBorder)
                    return t;
                else
                    return new Thickness(0.0d);

            }
            else
                return null;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

最后,您必须将控件添加到 MainWindow:

<Window x:Class="BorderButton.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:BorderButton"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <!-- Note that the BorderThickness has to be set to something! -->
        <local:BorderLabel Content="HelloWorld" Margin="118,68,318,218" MouseUp="BorderLabel_MouseUp" BorderBrush="Black" BorderThickness="2" ShowBorder="False" />
    </Grid>
</Window>

如您所见,WPF 稍微复杂一些……无论如何,现在您有两个示例可以开始!希望能帮助到你。

于 2012-12-04T12:15:27.847 回答
0

这是我发布的先前答案的链接。有人对按钮和自定义属性/设置感兴趣。它还展示了我如何开始采样和学习控件、自定义模板等并利用这些属性。您可以通过“触发器”(与您可以绑定的依赖项属性相关联)处理事件来扩展它。

我相信你会在那里找到许多其他样本,但这可能会帮助你同时不伤你的头撞墙:)

于 2012-12-04T12:20:49.490 回答