在 WPF 窗口中创建通用结构(主题)

本文关键字:结构 主题 WPF 窗口 创建 | 更新日期: 2023-09-27 17:57:11

我刚刚创建了一个 Windows 窗体应用程序来继承基本窗体的控件,它工作正常。

在 WPF XAML 中,是否可以将控件从基窗体继承到另一个基窗体,如上所示?

当我在视觉工作室中尝试时,我收到一个错误显示:"父子。MainWindow'不能是XAML文件的根目录,因为它是使用XAML定义的。

我的基窗 cs 代码:

namespace parentchild
    {
    public partial class BaseWindow : Window
        {
            public BaseWindow()
            {
                InitializeComponent();
            }
        }
}

我的基本窗口 xaml 代码:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dxr="http://schemas.devexpress.com/winfx/2008/xaml/ribbon" x:Class="parentchild.BaseWindow"
        Title="BaseWindow" Height="350" Width="525">
    <Grid>
        <StatusBar HorizontalAlignment="Left" Height="35" Margin="0,285,0,0" VerticalAlignment="Top" Width="517">
            <Label Content="Label"/>
            <Label Content="Label"/>
        </StatusBar>
    </Grid>
</Window>

我的子窗 cs 代码:

namespace parentchild
{
    public partial class childwindow : BaseWindow
    {
        public childwindow()
        {
            InitializeComponent();
        }
    }
}

我的子窗口 xaml 代码:

   <mn:BaseWindow x:Class="parentchild.childwindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mn="clr-namespace:parentchild"
            Title="childwindow" Height="300" Width="300">
        <Grid>
        </Grid>
    </mn:BaseWindow>

我通过创建一个用户控件并将其应用于所有窗口找到了另一种解决方案。这是正确的方法吗?

或者任何人都可以为所有Xaml窗口创建通用主题/结构的解决方案。

请为我提供解决此问题的解决方案。

在 WPF 窗口中创建通用结构(主题)

不能从 xaml 中定义的类继承。我可能会创建一个UserControl,并在您想要具有状态栏的任何窗口中将其用作"基本容器"。如果您打算制作一个基本窗口,您可以尝试这样的事情:

仅在代码中定义基本窗口:

public class MyWindowBase : Window
    {
        private ContentControl contentControl;
        public MyWindowBase()
        {
            this.CreateContent();
        }
        public Object BaseContent
        {
            get { return this.contentControl.Content; }
            set { this.contentControl.Content = value; }
        }
        private void CreateContent()
        {
            var grid = new Grid();
            var row1 = new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) };
            var row2 = new RowDefinition() { Height = GridLength.Auto };
            grid.RowDefinitions.Add(row1);
            grid.RowDefinitions.Add(row2);
            var statusBar = new StatusBar() { Height = 35, Background = Brushes.Blue }; // Initialize the status bar how you want.
            Grid.SetRow(statusBar, 1);
            this.contentControl = new ContentControl();
            grid.Children.Add(this.contentControl);
            grid.Children.Add(statusBar);
            base.Content = grid;
        }
    }

在 xaml 中使用基窗口,如下所示:

<WpfApplication7:MyWindowBase xmlns:WpfApplication7="clr-namespace:WpfApplication7"  x:Class="WpfApplication7.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="500">
    <WpfApplication7:MyWindowBase.BaseContent>
        <Button>
            Something
        </Button>
    </WpfApplication7:MyWindowBase.BaseContent>    
</WpfApplication7:MyWindowBase> 

当然,基类还有改进的余地,比如使 BaseContent 成为依赖属性,但我认为它展示了主要思想。

看起来您基本上是在尝试创建一个扩展Window的自定义控件。在 WPF 中创建自定义控件是一个复杂的主题,因为在决定如何实现自定义控件时需要考虑很多因素。看看这篇讨论这个问题的文章:

控件创作概述

最有可能的是,您实际上不需要自定义控件,而是需要自定义ControlTemplate(用 xaml 创作),以重新定义窗口的外观。您可以在Style中定义模板,并将该样式应用于所需的任何Window。在这里尝试在答案中解释很多内容,因此您应该阅读控件模板的工作原理以及它们如何有用。

如果您决定需要向自定义窗口添加新属性,则需要创建一个扩展Window并将这些属性添加为依赖项属性的新类(现在您有一个自定义控件)。然后,您可以在自定义ControlTemplate中使用这些属性来执行您希望它们执行的任何操作。

在 WPF 中工作与在 Windows 窗体中工作完全不同。如果您尝试将您在 Windows 窗体中学到的技术和做法应用于 WPF 应用程序,您将给自己带来很多麻烦。几年前,我进行了这种转变,我的建议是不要根据您从 Windows 窗体中了解到的内容对 WPF 做出任何假设。它们是完全不同的系统,具有不同的做事方式。