如何在普通窗口中使用无XAML的窗口子类?

lstz6jyr  于 2023-05-27  发布在  其他
关注(0)|答案(2)|浏览(149)

我有一个类EmptyWindow,它继承自WPF Window。它没有XAML,仅用于设置WindowStyle = None以删除Windows OS头。
我有一堆从EmptyWindow继承的窗口。我想模拟头没有复制/粘贴相同的代码50次。
我想要一个依赖/附加属性EmptyWindow.TitleContent,它将文本放置在窗口的顶部。
因此,子元素中的用法是EmptyWindow.TitleContent="A Child Title",而实际的子元素内容将进入EmptyWindow.Content
如果它是一个自定义的ContentControl,我会为它提供默认模板,TitleContent将绑定到网格行0中的ContentPresenter和行1中的Content
我不太清楚如何在Windows中实现同样的功能。
我做了什么(它不工作-继承的窗口应该在顶部显示“A Child Title”字符串,在中间显示“A WINDOW”,我有空的黑色窗口)
App.xaml

<Application x:Class="WindowSubclassing.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WindowSubclassing"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <Style TargetType="local:SlimWindow" BasedOn="{StaticResource {x:Type Window}}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:SlimWindow}">
                        <Grid Background="Blue">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <ContentPresenter ContentSource="TitleContent" />
                            <AdornerDecorator Grid.Row="1">
                                <ContentPresenter/>
                            </AdornerDecorator>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>    
    </Application.Resources>
</Application>

基本窗口类:

public class SlimWindow : Window
    {
        static SlimWindow()
        {
            var metaData = new FrameworkPropertyMetadata(typeof(SlimWindow));
            DefaultStyleKeyProperty.OverrideMetadata(typeof(SlimWindow), metaData);
        }

        public object TitleContent
        {
            get => GetValue(TitleContentProperty);
            set => SetValue(TitleContentProperty, value);
        }
        public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register(
            nameof(TitleContent), typeof(object), typeof(SlimWindow));
    }

最后一个窗口:

<local:SlimWindow x:Class="WindowSubclassing.AWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowSubclassing"
        mc:Ignorable="d"
        Title="AWindow" Height="450" Width="800" TitleContent="A Child Title">
    <Grid>
        <TextBlock Text="A WINDOW" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</local:SlimWindow>
a6b3iqyw

a6b3iqyw1#

自定义窗口类型应具有在Themes/Generic.xaml中定义的默认样式:

public class EmtpyWindow : Window
{
    static EmtpyWindow()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(EmtpyWindow),
            new FrameworkPropertyMetadata(typeof(EmtpyWindow)));
    }

    public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register(
        nameof(TitleContent), typeof(object), typeof(EmtpyWindow));

    public object TitleContent
    {
        get => GetValue(TitleContentProperty);
        set => SetValue(TitleContentProperty, value);
    }
}

主题/Generic.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApp1">
    <Style TargetType="local:EmtpyWindow" BasedOn="{StaticResource {x:Type Window}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:EmtpyWindow">
                    <Border Background="{TemplateBinding Background}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            BorderBrush="{TemplateBinding BorderBrush}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <ContentPresenter ContentSource="TitleContent" />
                            <AdornerDecorator Grid.Row="1">
                                <ContentPresenter/>
                            </AdornerDecorator>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Window1.xaml:

<local:EmtpyWindow x:Class="WpfApp1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="800"
        TitleContent="A Child Title">
    <Grid>
        <TextBlock>contents...</TextBlock>
    </Grid>
</local:EmtpyWindow>
u4vypkhs

u4vypkhs2#

如果不将新的默认Style添加到 Generic.xamlResourceDictionary中,则无法覆盖默认Style

static SlimWindow()
{
  var metaData = new FrameworkPropertyMetadata(typeof(SlimWindow));

  // The following line overrides the default template for the current control.
  // WPF will lookup the new Style in the Generic.xaml file,
  // and only in Gerneric.xaml.  
  DefaultStyleKeyProperty.OverrideMetadata(typeof(SlimWindow), metaData);
}

因为您已经将默认的Style添加到***App.xaml***中,所以WPF无法找到它。您的SlimWindow最终没有ControlTemplate,因此没有ContentPresenter来托管Window.Content值。
重要的一点是,WPF将只查找 * Generic.xaml * 文件中的默认样式,该文件必须位于 "\Themes” 文件夹中

方案一

要修复您的问题,请删除静态构造函数(并将Style保留在 * App.xaml * 中):

SlimWindow.cs

public class SlimWindow : Window
{
  public object TitleContent
  {
    get => GetValue(TitleContentProperty);
    set => SetValue(TitleContentProperty, value);
  }

  public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register(
            nameof(TitleContent), typeof(object), typeof(SlimWindow));}

App.xaml

<Application>
  <ResourceDictionary>
    <Style TargetType="SlimWindow">
    </Style>
  </ResourceDictionary>
</Application>

方案二

或者将Style移到 * Generic.xaml *(并保留静态构造函数):

SlimWindow.cs

public class SlimWindow : Window
{
  static SlimWindow()
  {
    var metaData = new FrameworkPropertyMetadata(typeof(SlimWindow));
    DefaultStyleKeyProperty.OverrideMetadata(typeof(SlimWindow), metaData);
  }

  public object TitleContent
  {
    get => GetValue(TitleContentProperty);
    set => SetValue(TitleContentProperty, value);
  }

  public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register(
            nameof(TitleContent), typeof(object), typeof(SlimWindow));}

泛型.xaml

<ResourceDictionary>
  <Style TargetType="SlimWindow">
  </Style>
</ResourceDictionary>

相关问题