重构WPF中的XAML

7

我的XAML文件变得很长,难以维护。我想知道是否有一种类似于重构的方法可以使用?

这里是一个简单的例子:

<Window x:Class="RefactorXAML.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Button>New</Button>
            <Button>Open</Button>
        </StackPanel>
    </Grid>
</Window>

我该如何重构 Stackpanel 部分并编写类似这样的内容?
<Window x:Class="RefactorXAML.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        // Refactored Markup
    </Grid>
</Window>

2
你尝试过使用样式(带控件模板)或用户控件吗?有什么原因不能使用它们吗? - Dan Puzey
1
我对这个有点新。你建议使用哪一个? - Vahid
3个回答

15

你可以将这些按钮放在一个用户控件中,使其变成以下形式:

<Window …
        xmlns:my="clr-namespace:SomeNamespace">
    <Grid>
        <my:NewAndOpenButtons />
    </Grid>
</Window>

你也可以用项控件(Items Control)来替换网格,它已经包含了那些按钮,但这样你会对其他内容强加过多限制,所以我不会这样做。

因此,针对上述情况,你的用户控件将类似于这样:

<UserControl x:Class="SomeNamespace.NewAndOpenButtons" …>
    <StackPanel>
        <Button>New</Button>
        <Button>Open</Button>
    </StackPanel>
</UserControl>

感谢poke, my是什么? - Vahid
@Vahid my 是指命名空间的引用。就像你在文件顶部有 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 中的 x 一样。你可以在这里了解更多相关信息。 - Loetn
1
@Vahid my: 前缀表示组件来自的 XML 命名空间。由于您的自定义组件不属于 Microsoft 内置组件命名空间,因此您必须定义自己的前缀。您可以随意命名(例如 my),如果这些组件在同一个程序集中定义,您可以使用我在答案中展示的语法进行定义。 - poke
1
@poke 再问一个问题。每个用户控件都有自己的代码后台。那么我在我的 MainWindow 中定义的变量将无法在“用户控件”中使用? - Vahid
2
@Vahid,没错,每个用户控件都是一个完全独立的控件,您无法访问其内部(就像您无法访问按钮的内部一样)。相反,如果您想允许与“外部”通信,则定义(依赖)属性,您可以在外部分配这些属性。 - poke
显示剩余2条评论

4

1) 使用内容控件

<Window.Resources>
    <ControlTemplate x:Key="Stackpanel" TargetType="ContentControl">
        <StackPanel>
            <Button>New</Button>
            <Button>Open</Button>
        </StackPanel>
    </ControlTemplate>
</Window.Resources>

<Grid>
    <ContentControl Template="{StaticResource Stackpanel}"></ContentControl>
</Grid>

2) 创建新的用户控件

图片描述

<UserControl x:Class="WpfApplication2.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
    <Button>New</Button>
    <Button>Open</Button>
</StackPanel>

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    xmlns:local="clr-namespace:WpfApplication2">

<Grid>
    <local:UserControl1></local:UserControl1>
</Grid>


在没有内容的情况下使用内容控件有点反模式。在这个例子中绝对没有理由使用内容控件,实际上使用一个会给人留下你可以添加内容的印象。 - poke
@poke好的,这里我使用ContentControl,因为Panel没有ContentTemplate属性。所以我们可以使用ContentControl来定义Panel的模板。不管怎样,我很感谢您的意见。谢谢 - Heena
谢谢Heena,我选择了第二种方法。 - Vahid
@HeenaPatil 这是因为面板不是控件(面板是定义如何呈现控件的组件)。您可以在此处使用任何其他控件,例如最基本的控件:Control,它没有进一步的语义(如content):) - poke

1
问题不仅仅是XAML重构,还包括全局代码重构。如果你的Window XAML太长,那么后台代码也会太长。
你应该通过将不同的功能放在不同的自定义控件中(UserControls是一个选择,但CustomControls更灵活)来重构你的UI界面,这样你的窗口就成为几个砖块的聚合体。

3
无论XAML中有什么,我的代码后置通常都是空的。 - poke
2
当一个应用程序组织良好时,后台代码通常很轻。但是,当大部分应用程序都在一个XAML文件中时,所有事件处理都发生在同一个地方,这就开始变得混乱了。 - Dmitry
1
我也有很长的XAML文件,几乎没有任何代码后台...只是说一下。 - Mashton

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