【问题标题】:How to define a custom class of a control, and define custom events and handlers in it (in WPF)?如何定义控件的自定义类,并在其中定义自定义事件和处理程序(在 WPF 中)?
【发布时间】:2012-11-22 01:16:24
【问题描述】:

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

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

有没有这方面的简单教程?

【问题讨论】:

    标签: wpf winforms events inheritance


    【解决方案1】:

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

    Generic.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>
    

    BorderLable.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 稍微复杂一些...无论如何,现在您有两个示例可以开始!希望对您有所帮助。

    【讨论】:

    • 非常感谢!我读了一篇关于这两者之间区别的简短博客,但是博客太简短了!我认为在这种特殊情况下,CustomControl 和 UserControl 都会为我发挥作用......我现在正在谷歌搜索。但是,如果您有任何链接或帖子或与此相关的任何内容,请与我分享。非常感谢;)
    【解决方案2】:

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

    我相信您会在那里找到许多其他示例,但这可能会帮助您同时不会因为撞墙而伤到头部 :)

    【讨论】:

    • 感谢您的帮助。但是 DependencyProperties 让我感到困惑 :D 而 CustomControl 对我来说很好;)
    猜你喜欢
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多