设想:
CustomWindow
带有自定义模板/ WindowChrome的WPF 窗口 ( ) 。- 问题:尝试在
Loaded
事件 throws中关闭窗口NullReferenceException
。 - 解决方法:
- 如果我注释掉
WindowChrome
setter,那么它就可以工作。- 但失去自定义镀铬
- 如果我在关闭窗口之前延迟了任意时间,那么它就可以工作。
- 使用延迟感觉不对
- 如果我注释掉
问题:
只有延迟解决方法允许我 1) 保留我的自定义窗口镶边和 2) 不引发异常。
但是延迟解决方案感觉就像一个黑客。
有一个更好的方法吗?
自定义窗口 xaml
<Style TargetType="v:CustomWindow">
<!-- Workaround 1: Works when commented out -->
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome UseAeroCaptionButtons="False" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type v:CustomWindow}">
<DockPanel Background="White">
<!-- Caption bar -->
<Grid Background="Cyan" DockPanel.Dock="Top">
<Grid Margin="5">
<!-- Title -->
<TextBlock FontSize="20" Text="{TemplateBinding Title}" />
<!-- Close button -->
<Button Width="30" Command="SystemCommands.CloseWindowCommand"
HorizontalAlignment="Right"
WindowChrome.IsHitTestVisibleInChrome="True"
Content="Close" />
</Grid>
</Grid>
<!-- Window content -->
<ContentPresenter Content="{TemplateBinding Content}" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
用法
var dialog = new CustomWindow();
dialog.Loaded += async delegate
{
// On loaded, do something, then close immediately
// await Task.Delay(10); // <-- Workaround 2: Uncomment this, and it seems to work
dialog.Close();
};
dialog.ShowDialog();
堆栈跟踪:
at System.Windows.Shell.WindowChromeWorker._ExtendGlassFrame()
at System.Windows.Shell.WindowChromeWorker._UpdateFrameState(Boolean force)
at System.Windows.Shell.WindowChromeWorker._ApplyNewCustomChrome()
at System.Windows.Shell.WindowChromeWorker._WindowSourceInitialized(Object sender, EventArgs e)
at System.Windows.Window.OnSourceInitialized(EventArgs e)
at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
at System.Windows.Window.CreateSourceWindowDuringShow()
at System.Windows.Window.SafeCreateWindowDuringShow()
at System.Windows.Window.ShowHelper(Object booleanBox)
at System.Windows.Window.Show()
at System.Windows.Window.ShowDialog()
环境:
- 视窗 10 专业版
- 视觉工作室 2017
- .NET 4.6.1
解决方案
将代码更改为以下作品:
var dialog = new CustomWindow();
dialog.Loaded += delegate
{
Dispatcher.BeginInvoke(new Action(
delegate
{
// On loaded, do something, then close immediately
dialog.Close();
})
);
};
dialog.ShowDialog();