Setting WindowStartupLocation from ResourceDictionary throws XamlParseException

When I try to set the WindowStartupLocation property via Setter within a ResourceDictionary , I get a XamlParseException :

'Set the' System.Windows.Setter.Property 'property throws an exception.' Line number "x" and line position "y".

The internal exception is ArgumentNullException :

The value cannot be null. Parameter Name: Property.

My style in the resource dictionary:

 <Style TargetType="Window" x:Key="WindowStyle"> <Setter Property="SizeToContent" Value="WidthAndHeight" /> <Setter Property="ResizeMode" Value="CanMinimize" /> <Setter Property="WindowStartupLocation" Value="CenterOwner" /> </Style> 

The problem is not using ResourceDictionary , since when deleting WindowStartupLocation two other properties ( SizeToContent and ResizeMode ) are set as expected in windows that reference the style:

 <Window x:Class="WpfApplication1.MyWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Style="{DynamicResource WindowStyle}"> <Window.Resources> <ResourceDictionary Source="MyResourceDictionary.xaml" /> </Window.Resources> </Window> 

Has anyone come across this? Is this a bug / limitation of WPF?

PS I know that this question is similar to the Window Startup Location from the resource dictionary , but there is not enough information in another question that subsequently remained unresolved.

+7
source share
2 answers

The problem is that WindowStartupLocation is not DependencyProperty, so you cannot set it in the style customizer. Looking at ILSpy, Setter calls

 CheckValidProperty(DependencyProperty property) 

and throws a NullArgumentException.

Since WindowStartupLocation is just a CLR property, it cannot be set this way.

Edit: To respond to the comment. You can still use ResourceDictionary :

 <Application.Resources> <ResourceDictionary> <Style x:Key="WindowStyle" TargetType="Window"> <Setter Property="SizeToContent" Value="WidthAndHeight" /> <Setter Property="ResizeMode" Value="CanMinimize" /> </Style> <WindowStartupLocation x:Key="WSL">CenterOwner</WindowStartupLocation> </ResourceDictionary> </Application.Resources> <Window x:Class="WpfApplication7.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowStartupLocation="{StaticResource WSL}" Style="{StaticResource WindowStyle}" /> 
+8
source

WindowStartupLocation is a CLR property, this can be seen in ILSpy :

 [DefaultValue(WindowStartupLocation.Manual)] public WindowStartupLocation WindowStartupLocation { get { this.VerifyContextAndObjectState(); this.VerifyApiSupported(); return this._windowStartupLocation; } set { this.VerifyContextAndObjectState(); this.VerifyApiSupported(); if (!Window.IsValidWindowStartupLocation(value)) { throw new InvalidEnumArgumentException("value", (int)value, typeof(WindowStartupLocation)); } this._windowStartupLocation = value; } } 

In style settings, only a dependency property can be specified. There are two ways to solve this problem:

  • inherit the Window class and create a class with the WindowStartupLocation dependency WindowStartupLocation

  • create a related property type dependent on WindowStartupLocation and define the logic in PropertyChanged

The first method is cumbersome because you need to override the class for a single property. The second method is preferred and the behavior will be applied, but I will call PropertyExtension .

Here is the complete code:

 namespace YourProject.PropertiesExtension { public static class WindowExt { public static readonly DependencyProperty WindowStartupLocationProperty; public static void SetWindowStartupLocation(DependencyObject DepObject, WindowStartupLocation value) { DepObject.SetValue(WindowStartupLocationProperty, value); } public static WindowStartupLocation GetWindowStartupLocation(DependencyObject DepObject) { return (WindowStartupLocation)DepObject.GetValue(WindowStartupLocationProperty); } static WindowExt() { WindowStartupLocationProperty = DependencyProperty.RegisterAttached("WindowStartupLocation", typeof(WindowStartupLocation), typeof(WindowExt), new UIPropertyMetadata(WindowStartupLocation.Manual, OnWindowStartupLocationChanged)); } private static void OnWindowStartupLocationChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { Window window = sender as Window; if (window != null) { window.WindowStartupLocation = GetWindowStartupLocation(window); } } } } 

Usage example:

 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PropertiesExtension="clr-namespace:YourProject.PropertiesExtension"> <Style TargetType="{x:Type Window}"> <Setter Property="PropertiesExtension:WindowExt.WindowStartupLocation" Value="CenterScreen" /> <Setter Property="Width" Value="723" /> <Setter Property="Height" Value="653" /> <Setter Property="Title" Value="MainWindow title string" /> </Style> </ResourceDictionary> 
+5
source

All Articles