简体   繁体   English

如何在WPF中进行自定义控件

[英]How to make custom control in WPF

In winforms there were 2 templates: UserControl allows to make composite control (group of existing controls) to reuse it and standardize operations with it, CustomControl was a fully custom control (often rendered manually, performing differently than standard controls, etc), allowing overriding and provides access to protected things. 在winforms中有2个模板: UserControl允许制作复合控件(一组现有控件)以重用它并对其进行标准化操作, CustomControl是完全自定义的控件(通常是手动呈现的,其执行方式与标准控件不同,等等),从而可以覆盖并提供对protected事物的访问。

In wpf I only found UserControl template (using express edition of VS). 在wpf中,我仅找到UserControl模板(使用VS的快速版)。

To create custom MyControl I am doing following: 要创建自定义MyControl我正在执行以下操作:

  • create normal class, based on Control / ContentControl ; 根据Control / ContentControl创建普通的类;
  • create resource dictionary with Style containing control template (could be only ControlTemplate , style is better, because can contain other properties setter) 使用包含控件模板的Style创建资源字典(只能是ControlTemplate ,样式更好,因为可以包含其他属性设置器)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:MySolution">
    <Style x:Key="MyControl" TargetType="local:MyControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyControl">
                    <Grid x:Name="PART_Grid">
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
  • bind them together like this 这样把他们在一起

public class MyControl : Control
{
    public MyControl()
    {
        var dictionary = new ResourceDictionary();
        dictionary.Source = new Uri("/MySolution;component/MyControl.xaml", UriKind.Relative);
        Style = dictionary["MyControl"] as Style;
        Loaded += MyControl_Loaded;
    }
}
  • define lazy parts accessors in template 在模板中定义惰性部件访问器

private Grid _partGrid;
private Grid PartGrid
{
    get
    {
        if (_partGrid == null)
            _partGrid = (Grid)Template.FindName("PART_Grid", this);
        return _partGrid;
    }
}

It works, but I am not sure if its the most optimal way: 它有效,但是我不确定它是否是最佳方法:

  • .cs and .xaml are separate files (not one entity as in case of wpf UserControl ); .cs.xaml是单独的文件(不是wpf UserControl一个实体 );
  • when moving xaml (to example, inside Controls folder) constructor code has to be adjusted; 移动xaml (例如,在Controls文件夹内),必须调整构造函数代码;
  • parts accessor are not available in constructor (template is yet not loaded). 零件访问器在构造函数中不可用(尚未加载模板)。

My question: is there better way to make custom control with template? 我的问题:有没有更好的方法可以通过模板进行自定义控件? More comfortable, automatic, with automatic parts accessors, etc. 更舒适,更自动,带有自动零件配件等


Here are my wpf templates 这是我的WPF模板

It is better if you use the CustomControl VS template, not sure why you don't see it, maybe because you are using the Express version. 最好使用CustomControl VS模板,不确定为什么看不到它,可能是因为您使用的是Express版本。 That template generates a Generic.xaml file for you, there you define the styles/controltemplate. 该模板将为您生成Generic.xaml文件,您可以在其中定义样式/控件模板。 Also you will have the .cs with the c# definition of your control. 此外,您还将拥有带有控件的c#定义的.cs。

To get the diferent parts of your control, the recommended way is using the GetTemplateChild mehtod and pass the Part_Name and you normally do that overriding the OnApplyTemplate() method. 要获取控件的不同部分,建议的方法是使用GetTemplateChild方法,并传递Part_Name,通常您会覆盖OnApplyTemplate()方法。

 public override void OnApplyTemplate()
  {
    base.OnApplyTemplate();

    ActionBtn = GetTemplateChild(BtnPartName) as ButtonBase;
    ContentPopup = GetTemplateChild(PopupPartName) as Popup;
  }

Take a look to this post to check a sample with the details of that implementation. 请看一下这篇文章,以查看包含该实现细节的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM