如何解决作为 CustomControl 实现的 WPF 窗口在设计时不应用模板
我正在尝试将 WPF 窗口实现为 CustomControl,以便我可以覆盖默认的 WindowChrome 并在一套应用程序中创建我自己的可重用外观。我有一个正在运行的演示项目,它将在运行时自动将自定义控件样式模板应用到窗口,但我很难让它在设计时正常工作。
我意识到这是 WPF custom window does not apply its generic template at design time 的副本,但没有适用于我的用例的问题的适用答案。我的演示在同一个项目中包含所有内容,因此目标 cpu 不匹配没有问题。而且我必须重新设计窗口的样式,所以仅仅替换内容控制部分也不起作用。
这是我的基本窗口类 (Classes\WindowBase.cs),带有用于测试的附加依赖项属性:
using System.Windows;
namespace WPFTestwindowSubclassing.Classes
{
public class WindowBase : Window
{
public string ContentText
{
get { return (string)GetValue(ContentTextProperty); }
set { SetValue(ContentTextProperty,value); }
}
public static readonly DependencyProperty ContentTextProperty =
DependencyProperty.Register(
"ContentText",typeof(string),typeof(WindowBase),new PropertyMetadata(string.Empty));
}
}
还有我的 CustomControl 窗口类 (CustomContorls\CustomWindow.cs):
using System.Windows;
using System.Windows.Controls;
using WPFTestwindowSubclassing.Classes;
namespace WPFTestwindowSubclassing.CustomControls
{
[TemplatePart(Name = "PART_CloseButton",Type = typeof(Button))]
public class CustomWindow : WindowBase
{
static CustomWindow()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(CustomWindow),new FrameworkPropertyMetadata(typeof(CustomWindow)));
}
public override void OnApplyTemplate()
{
((Button)GetTemplateChild("PART_CloseButton")).Click += (s,e) => this.Close();
ContentText += " Internal Template Applied.";
base.OnApplyTemplate();
}
}
}
窗口的样式资源 (ResourceDictionaries\CustomControls\CustomWindowStyle.xaml):
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:WPFTestwindowSubclassing.CustomControls">
<Style
x:Key="{x:Type cc:CustomWindow}"
targettype="{x:Type cc:CustomWindow}">
<Setter Property="Background" Value="AliceBlue" />
<Setter Property="AllowsTransparency" Value="True" />
<Setter Property="WindowStyle" Value="None" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome
CaptionHeight="30"
CornerRadius="0"
GlassFrameThickness="0"
NonClientFrameEdges="None"
ResizeBorderThickness="10"
UseAeroCaptionButtons="False" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate targettype="{x:Type cc:CustomWindow}">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Button
x:Name="PART_CloseButton"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Height="30" Width="30"
WindowChrome.IsHitTestVisibleInChrome="True"/>
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
我的主题\Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="../ResourceDictionaries/CustomControls/CustomWindowStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
最后,我的 MainWindow.xaml 和 MainWindow.xaml.cs:
<cc:CustomWindow
x:Class="WPFTestwindowSubclassing.MainWindow"
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:cc="clr-namespace:WPFTestwindowSubclassing.CustomControls"
mc:Ignorable="d"
Title="MainWindow"
Height="300"
Width="400"
ContentText="Hello?"
Loaded="Window_Loaded">
<Grid>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type cc:CustomWindow}},Path=ContentText}"
Grid.RowSpan="2" />
</Grid>
</cc:CustomWindow>
using System.Windows;
using WPFTestwindowSubclassing.CustomControls;
namespace WPFTestwindowSubclassing
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : CustomWindow
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender,RoutedEventArgs e)
{
ContentText += " Window Loaded!";
}
public override void OnApplyTemplate()
{
ContentText += " Template Applied!";
base.OnApplyTemplate();
}
}
}
这不是一个完整的漂亮风格的实现,但足以重现问题。当我运行项目时,这一切都有效。窗口是无框的,调整大小手柄仍然有效,关闭按钮有效。但是在 Visual Studio XAML 设计器中,它看起来仍然像一个常规窗口。我可以通过手动将样式应用到 Window 来强制它工作:
<cc:CustomWindow
...
Style="{StaticResource {x:Type cc:CustomWindow}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="ResourceDictionaries/CustomControls/CustomWindowStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
...
但是为什么在运行时需要这种额外的直接样式分配?有没有更简单的方法让窗口在设计时像任何其他 CustomControl 实现一样“正常工作”?
我从一个类似的问题中找到了这个答案 (https://stackoverflow.com/a/59297503/1236614),该问题似乎表明 VS XAML 设计器在显示窗口方面正在做一些奇怪的幕后胡说八道,但这真的是发生了什么?这也可以解释为什么绑定到 Window 的 Title 或我的 CustomWindow 的 ContentText 属性在设计时也不起作用 - 设计时祖先可能不是真正的“窗口”。一定有办法解决这个问题,对吧?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。