C# 如何在 WPF 中制作模板窗口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/420538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:43:15  来源:igfitidea点击:

How to make a Template Window in WPF?

c#wpfwpf-controls

提问by NoizWaves

So i am building an application that will have lots of windows, all with the same basic layout:

所以我正在构建一个应用程序,它将有很多窗口,所有窗口都具有相同的基本布局:

  1. A main Window
  2. A logo in the top corner
  3. A title block
  4. A status displayer down the bottom
  5. An area for window specific controls.
  1. 一个主窗口
  2. 顶角的标志
  3. 标题栏
  4. 底部的状态显示器
  5. 窗口特定控件的区域。

At the moment i have to recreate this structure in every window. Ideally i want this layout to be coded in a single place, perhaps into a custom Window subclass for ease of use. Does anyone have any clues for how to get started, or previous experience with similar problems?

目前我必须在每个窗口中重新创建这个结构。理想情况下,我希望将此布局编码在一个地方,可能会编码到自定义 Window 子类中以方便使用。有没有人有任何关于如何开始的线索,或者以前遇到过类似问题的经验?

采纳答案by Ian Oakes

You can create a new ControlTemplate that targets a window to accomplish this as shown below.

您可以创建一个以窗口为目标的新 ControlTemplate 来完成此操作,如下所示。

<ControlTemplate x:Key="WindowControlTemplate1" TargetType="{x:Type Window}">
    <Border 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="{TemplateBinding BorderThickness}"
        >
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="0.93*"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="0.21*"/>
                <ColumnDefinition Width="0.79*"/>
            </Grid.ColumnDefinitions>

            <ContentPresenter 
                Grid.ColumnSpan="2" 
                Grid.Row="1" 
                Content="{TemplateBinding Content}" 
                ContentTemplate="{TemplateBinding ContentTemplate}"
                />
            <ResizeGrip 
                HorizontalAlignment="Right" 
                x:Name="WindowResizeGrip" 
                VerticalAlignment="Bottom" 
                IsTabStop="False" 
                Visibility="Collapsed" 
                Grid.Column="1" 
                Grid.Row="2"
                />
            <TextBlock Text="My Logo" />
            <TextBlock Grid.Column="1" Text="My Title"/>
            <StatusBar Height="20" Grid.ColumnSpan="2" Grid.Row="2"/>
        </Grid>
    </Border>

    <ControlTemplate.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="ResizeMode" Value="CanResizeWithGrip"/>
                <Condition Property="WindowState" Value="Normal"/>
            </MultiTrigger.Conditions>
            <Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/>
        </MultiTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

回答by Stephen Wrighton

why exactly are you using "lots of windows?" Why not just a single window with a tab control? Or a single window with user controls?

你为什么要使用“很多窗口”?为什么不只是一个带有选项卡控件的窗口?还是带有用户控件的单个窗口?

Regardless, to answer your question, usercontrols are one way you want to get the functionality that you're describing as wanting.

无论如何,为了回答您的问题,用户控件是您希望获得您所描述的功能的一种方式。

Create a new Window class, and have it have a "Childrens" property which allows for an object to get embedded into the dock panel where you want the "window specific controls" to go.

创建一个新的 Window 类,并使其具有“Childrens”属性,该属性允许将对象嵌入到您希望“窗口特定控件”所在的停靠面板中。

As you launch new windows, instantiate the window type, and a user control with the specific controls, add the user control to the Children property of your window, and then show the window. You can even tie up event handlers, DataContexts and what not at this time.

当您启动新窗口时,实例化窗口类型和具有特定控件的用户控件,将用户控件添加到窗口的 Children 属性,然后显示该窗口。您甚至可以绑定事件处理程序、DataContexts 以及目前没有的东西。

回答by Rhys

If you're brave enough to take a big architectural shift you could consider CompositeWPF(previously codenamed Prism) from the Patterns & Practices guys at Microsoft.

如果您有足够的勇气进行重大的架构转变,您可以考虑来自 Microsoft Patterns & Practices 人员的CompositeWPF(以前代号为 Prism)。

Of interest to you would be the ability to define "regions" in a shell (i.e. window) and then using views to fill the regions. It uses the Model-View-Presenter pattern to allow independent development of "views" from the model than can be easily be relocated over time as the shell only defines regions and is not coupled directly to what is placed in to it. Principally this helps decouple the shell from the views and the views from each other and make it easier to unit-test ... blah, blah blah.

您感兴趣的是能够在外壳(即窗口)中定义“区域”,然后使用视图来填充这些区域。它使用 Model-View-Presenter 模式允许从模型中独立开发“视图”,随着时间的推移可以很容易地重新定位,因为 shell 只定义区域,而不直接与放置在其中的内容耦合。主要是这有助于将外壳与视图和视图相互分离,并使单元测试更容易......等等,等等。

It is a big jump and something that will slow you down to begin with, although your situation is one of the types of applications that CompositeWPF is meant to address.

尽管您的情况是 CompositeWPF 旨在解决的应用程序类型之一,但这是一个很大的飞跃,并且会使您从一开始就放慢速度。

As part of CompositeWPF you will need to take on board various patterns that can confuse newcomers, e.g. The UnityContainer, inversion-of-control, MVP (or Model/view/view-model) and dependency injection.

作为 CompositeWPF 的一部分,您将需要了解可能使新手感到困惑的各种模式,例如 UnityContainer、控制反转、MVP(或模型/视图/视图模型)和依赖项注入。

I can remember when I first started with the sample apps being puzzled because it is not obvious how on earth the some of the views were even being created! The unity container will instantiate objects and call parameterised constructors magically.

我记得当我第一次开始使用示例应用程序时感到困惑,因为有些视图到底是如何创建的并不明显!统一容器将实例化对象并神奇地调用参数化构造函数。

CompositeWPF is an elegant solution to your question but not a simple or straightforward one. Having used CompositeWPF in my last project I intend to use it again for the next appropriate application.

CompositeWPF 是您问题的优雅解决方案,但不是简单或直接的解决方案。在上一个项目中使用了 CompositeWPF 后,我打算在下一个适当的应用程序中再次使用它。

回答by Hades32

The most simple approach is to create WPF a "Page" for the window specific controls and place a "Frame" in the main window. You can even create a nice navigation this way.

最简单的方法是为窗口特定控件创建 WPF 一个“页面”,并在主窗口中放置一个“框架”。您甚至可以通过这种方式创建一个不错的导航。