什么是UserControl的目的?

14
为什么我们实际上需要一个用户控件?
窗口:
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1">

    <wpfApplication1:SaveCloseUserControl />

</Window>

用户控制:

<UserControl x:Class="WpfApplication1.SaveCloseUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Horizontal">
    <Button Height="30" Content="Save" />
    <Button Height="30"
            Margin="1"
            Content="Cancel" />
</StackPanel>
</UserControl>

后台代码:

public partial class SaveCloseUserControl : UserControl
{
    public SaveCloseUserControl()
    {
        InitializeComponent();
    }
}

如果以下代码没有使用UserControl也能达到同样的效果,我就看不出为什么要将StackPanel(或任何其他控件)包装在UserControl中。

窗口:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1">

    <wpfApplication1:SaveCloseStackPanel />

</Window>

没有用户控制的堆栈面板:

<StackPanel x:Class="WpfApplication1.SaveCloseUserControl"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Orientation="Horizontal">
    <Button Height="30" Content="Save" />
    <Button Height="30"
            Margin="1"
            Content="Cancel" />
</StackPanel>

后台代码:

 public partial class SaveCloseUserControl : StackPanel
 {
    public SaveCloseUserControl()
    {
        InitializeComponent();
    }
 }

我一直在使用用户控件,但现在我想起来它们除了将一个项目包装起来之外并没有做什么。所以我在10个不同的视图上尝试了它,无论是什么,我都能用其他项目(Grid、ComboBox、GroupBox等)代替用户控件,而且它们的工作方式完全相同。所以明确一下,如果我的用户控件中第一项是ComboBox,那么我删除用户控件并将ComboBox放在原处,里面的所有东西都会保持不变,就像上面的StackPanel示例一样。

既然用户控件没有任何作用,为什么我还要费心去创建和渲染另一个项目呢?


1
你如何在多个地方重复使用该组件,同时提供其自己的数据验证规则和其他视图模型无关的功能呢?啊哈哈.... :D - Chris W.
@ChrisW。与用户控件完全相同的方式,因为我所做的一切就是在此情况下(xaml文件的开始和结束标记),将UserControl标记替换为StackPanel。验证、绑定等等,一切都像以前一样正常工作。 - adminSoftDK
啊,好的,我没注意到你已经在创建自己的类了。那么,是的,我明白你的观点。我想争论应该更倾向于代码维护方面,因为我知道如果我要介入一个大型项目并发现东西被堆在非标准的方式中,我会在内心深处默默流泪的。除非有人能够提供技术上明确定义的答案,否则我认为这可能会成为一个充满意见交流的问题。 - Chris W.
是的,它会工作,但使用UserControl就像使用Person类而不是Manager类一样,即使Manager也是Person。 我们应该尽可能去到类层次结构的顶部。 StackPanel是一个用户控件,但它是一个特殊的用户控件,而不是通用的。 - Omar Zaarour
在第二个例子中,您有<wpfApplication1:SaveCloseStackPanel />,但是<StackPanel x:Class="WpfApplication1.SaveCloseUserControl" …>public partial class SaveCloseUserControl : StackPanel。我猜所有的都应该是SaveCloseStackPanel - Palec
显示剩余3条评论
4个回答

17
UserControl的作用是将一组控件封装到一个可重用的组件中,它们不能被样式化或模板化。 Custom Control的目的是扩展现有控件或创建全新的控件。与UserControl相比,Custom Control可以被样式化和模板化。
你可能把这两个搞混了。
因此,你可能会想知道:“我何时应该使用UserControl,何时应该使用Custom Control?”答案是取决于具体情况。
当您需要创建一组逻辑上相互交互以创建几乎成为一个复合控件的控件时,应使用UserControl。当您希望向现有控件添加功能时,则应使用Custom Control
在您的示例中,最好使用UserControl,因为您的StackPanel是由一组控件制作成一个可重用的组件。
您可以在此处此处了解更多信息。

谢谢您的回答。我理解了它们之间的区别,但我并不认为有必要使用UserControl。如果UserControl中的第一个项目可以代替整个UserControl,并且其行为方式完全相同,那么我可以重用它等等,但是我会少一个控件,这应该是一件好事。 - adminSoftDK
1
除了Mike的评论之外,只有当您知道需要多次使用这样的控件集合时才创建用户控件。另一个使用用户控件的案例是MVVM开发中的视图。所有视图都只是控件的集合,可以重复使用。 - Neeraj
@adminSoftDK,你的论点的逻辑延伸意味着我们不需要结构体或类(抽象数据类型,一般而言),因为它们“仅仅”是聚合了更多基本类型和相关行为。更简单的“事物”的聚合 - 无论是控件还是更简单的数据类型,以及将它们联系在一起的任何相关“逻辑”,都是非常有价值的面向对象编程设施。用户控件正是提供这种功能的。当然,如果您的需求相当简单,用户控件可能会过度设计(就像有时候结构体或类可能会过度设计一样),但在其他情况下它非常有用。 - Vatsan
@adminSoftDK,我也认为你忽略了这个答案的第一句话。如果您使用特定面板,则可能会得到不同的结果,因为该面板可以在项目中进行全局样式设置。使用UserControl就不会有这个问题。 - kkCosmo

3
UserControl 的目的是帮助您构建可重用的 UI 组件,这些组件可以像内置控件一样添加到工具箱中。这里的 "User" 前缀有点像是 "不来自 WPF 团队"。WPF 不包含任何从 UserControl 派生的类。
UserControl 的一个非常重要的方面是,您可以使用 XAML 设计它们(因此它们可以是复合的),并将代码和 XAML 打包在一起,可能在无需源代码的情况下制作一个“库”程序集。
现在,您的示例很少(没有冒犯的意思:-),它们没有展示出足够有趣的特性,让我想把它们变得真正可重用。大多数情况下,您将根据用法(或经验)构建 UserControls,在重复相同的 XAML 模式超过一次之后,也许还有一些变化。
例如,在这个开源项目中(Github for Visual Studio):https://github.com/github/VisualStudio/tree/master/src/GitHub.UI/Controls,您会看到他们编写了一些自定义控件,如 EmojiImage(从 Image 派生,不需要 XAML),以及一个 UserControl:HorizontalShadowDivider。为什么?因为 HorizontalShadowDivider 与 XAML 相关联,并且(可能)用于多个地方。

2

我曾经在某本书上(抱歉,忘记书名了...)看到过UserControl被称为“块盒子”容器。

根据我的理解和您的示例,您可以看到派生自StackPanel的控件只能使用StackPanel来布局两个按钮 - 要么是水平的,要么是垂直的。如果将来布局发生变化(也许有新需求?),您需要创建一个新的派生类(或重写现有的派生类)并使用它,比如DockPanel。这很糟糕。

而对于派生自UserControl的控件,您只需将StackPanel更改为适合新需求的另一种面板类型即可。

这就是我认为UserControl是块盒子的原因。


1
根据你的例子,如果您只使用用户控件一次,则它并不是很有用。但在这种情况下,如果某些设计部分被多次使用,并且每次都编写xaml代码或任何其他逻辑来创建相同的UI,则用户控件就会发挥作用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接