C# 从ResourceDictionary设置WindowsStartUpLocation会引发XamlParseException

C# 从ResourceDictionary设置WindowsStartUpLocation会引发XamlParseException,c#,wpf,.net-4.0,resourcedictionary,C#,Wpf,.net 4.0,Resourcedictionary,当我试图通过ResourceDictionary中的Setter设置WindowStartupLocation属性时,我得到一个XamlParseException: “Set property”System.Windows.Setter.property“引发了异常。行号“x”和行位置“y” 内部异常是一个ArgumentNullException: 值不能为null。参数名称:属性 我在资源字典中的风格是: <Style TargetType="Window" x:Key="Windo

当我试图通过
ResourceDictionary
中的
Setter
设置
WindowStartupLocation
属性时,我得到一个
XamlParseException

“Set property”System.Windows.Setter.property“引发了异常。行号“x”和行位置“y”

内部异常是一个
ArgumentNullException

值不能为null。参数名称:属性

我在资源字典中的风格是:

<Style TargetType="Window" x:Key="WindowStyle">
    <Setter Property="SizeToContent" Value="WidthAndHeight" />
    <Setter Property="ResizeMode" Value="CanMinimize" />
    <Setter Property="WindowStartupLocation" Value="CenterOwner" />
</Style>
有人遇到过这种情况吗?这是WPF的缺陷/限制吗


另外,我知道这个问题与类似,但在另一个问题中没有提供足够的信息,而这个问题后来一直没有解决。

问题是WindowsStartUplocation不是从属属性,因此您无法在样式设置器中设置它。查看设置程序调用的ILSpy

CheckValidProperty(DependencyProperty property)
并抛出一个NullArgumentException

由于WindowsStartUpLocation只是一个CLR属性,因此不能以这种方式设置

编辑:
以回复评论。您仍然可以使用
资源字典

<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}" />

中心所有者

WindowStartupLocation
是一个CLR属性,可以在以下内容中看到:

在样式设置程序中,只能指定依赖项属性。有两种方法可以解决此问题:

  • 继承类
    Window
    ,并使用依赖属性
    WindowStartupLocation

  • 根据
    WindowStartupLocation
    创建附加的属性类型,并在PropertyChanged中定义逻辑

第一个方法很麻烦,因为需要为一个属性重新定义类。第二种方法是首选方法,将附加到行为,但我将调用
PropertyExtension

以下是完整的代码:

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);
            }
        }
    }
}
使用的示例:

<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>


所以您可以直接从XAML(使用
语法)设置CLR(非依赖性)属性,但不能从资源字典设置,对吗?不完全如此。您可以直接在XAML中设置属性,但仍然可以使用资源字典,而不是样式。也就是说,下面的作品:CenterOwner谢谢,非常有用!不幸的是,我不能使用
StaticResource
,因为我需要从
窗口
引用
ResourceDictionary
(我正在开发一个Office加载项,它不能为我提供WPF
应用程序
类)。但是你的建议对于在Windows应用程序中集中默认样式将是非常好的。。这是一个正确的解决方案:)
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);
            }
        }
    }
}
<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>