Wpf 用户控件的用途是什么?

Wpf 用户控件的用途是什么?,wpf,xaml,user-controls,Wpf,Xaml,User Controls,为什么我们实际上需要一个用户控件 窗口: <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

为什么我们实际上需要一个用户控件

窗口:

<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>
<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>
如果下面没有UserControl的代码也会这样做,我看不出有什么理由要在UserControl中包装StackPanel(或任何其他控件)

窗口:

<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>
<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>
我在任何地方都使用过用户控件,但现在当我想到它时,它们除了在其中包装一个项目之外什么都不做。因此,我在10个不同的视图上尝试了它,不管它是什么,我能够用其他项(网格、组合框、GroupBox等)替换UserControl,并且它的工作方式完全相同。所以说得很清楚,如果我有一个用户控件,其中的第一件事是ComboBox,那么我移除了UserControl并将ComboBox放在它的位置上。然后里面的所有东西都保持原样,就像上面的StackPanel示例一样


为什么我还要为UserControl费心,如果它不起任何作用,我还要创建和呈现另一个项目?

用户控件的目的是将一组控件组合成一个可重用的组件。它们不能设置样式或模板

自定义控件的目的是扩展现有控件,或创建全新控件。与
用户控件相反,这些控件可以设置样式和模板

我想你把这两个人搞混了

因此,您可能会想,“我什么时候应该使用
UserControl
以及什么时候应该使用
自定义控件
?”答案是这取决于具体情况

当您需要创建一组逻辑控件时,应该使用
UserControl
,这些控件以某种方式交互以创建一个几乎复合的控件。如果要向现有控件添加功能,应使用自定义控件

在您的示例中,最好的方法是使用
UserControl
,因为
StackPanel
是由一组控件组成的可重用组件


您可以找到更多信息。

用户控件的目的是帮助您构建可重用的UI组件,这些组件可以像内置控件一样添加到工具箱中,从无到有。 这里前缀“User”的意思是“不是来自WPF团队”。WPF不提供从
UserControl
派生的任何类

UserControls的一个非常重要的方面是,您可以使用XAML设计它们(因此它们可以是复合的),并将代码+XAML打包在一起,可能是在一个“库”程序集中,您可以在没有源代码的情况下发布

现在,您的示例非常贫乏(无意冒犯:-),它们没有做任何有趣的事情,我很想让它们真正可重用。大多数情况下,在意识到已经多次重复了相同的XAML模式(可能有一些变化)之后,您将根据使用情况(或经验)构建UserControls


例如,在这个开源项目(Github For Visual Studio)中,您将看到他们编写了一些自定义控件,如EmojiImage(它派生自Image,不需要XAML)和一个用户控件:HorizontalShadowDivider。为什么?因为HorizontalShadowDivider与XAML关联,并且(可能)在多个地方使用。

我从一本书的某个地方读到过(很抱歉忘记了书名…),UserControl是一个“块盒”容器

根据我对该术语的理解,并以您的示例为基础,您可以看到,
StackPanel
派生的按钮受限于StackPanel布局两个按钮的能力,这两个按钮可以是水平的,也可以是垂直的。将来,如果这个布局发生变化(可能是一个新的需求?),您将需要创建一个新的面板派生类(或重写现有的类)并使用它,比如DockPanel。这很糟糕

UserControl
派生面板上,您所要做的就是将StackPanel更改为另一种适合新需求的面板类型


这使得用户控件成为一个块框,IMHO。

根据您的示例,如果您只使用了一次用户控件,那么它就没有多大用处了。
但是在这种情况下,如果某个设计部件被多次使用,并且每次您编写xaml代码或任何其他逻辑来创建相同的UI,那么用户控制就起作用了。

您将如何在多个位置重复使用该组件,同时提供其自己的一组内容,如数据验证规则和其他与viewmodel无关的功能?啊哈D@ChrisW. 与usercontrol完全相同,因为我所做的只是在本例中用StackPanel(xaml文件的开始和结束标记)替换标记usercontrol。验证、绑定等,一切都按原样进行。啊,好吧,我没有注意到你已经在创建自己的类了。那我明白你的意思了。我想争论会更倾向于代码维护问题,因为我知道如果我不得不进入一个大项目的新阶段,发现一些东西以非标准的方式聚集在一起,我会在里面笑一笑。除非有人能提供一个技术定义的答案,否则我会看到这变成一个关于观点的聊天讨论类问题。是的,它会起作用,但使用UserControl就像使用Person类而不是Manager类,即使经理是个人。我们应该尽可能深入到类层次结构的顶部。Stack panel是一个用户控件,但它是一个特殊的用户控件而不是一般的用户控件。@OmarZaarour这对我来说不一样,因为如果我使用UserControl,然后在其中使用Stack panel。我创建了两个对象,而不是一个,而不需要其中一个不起任何作用。所以我不太明白你评论的人/经理和我的问题之间的类比,但谢谢你的回答:)谢谢你的回答。我理解其中的区别,我根本不认为需要使用UserControl。如果
<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();
    }
 }