Установка WindowStartupLocation из ResourceDictionary выбрасывает исключение XamlParseException

Когда я пытаюсь установитьWindowStartupLocation собственность черезSetter в пределахResourceDictionary, Я получаюXamlParseException:

'Установить свойство' System.Windows.Setter.Property 'вызвала исключение.' Номер строки 'x' и позиция строки 'y'.

Внутренним исключением являетсяArgumentNullException:

Value не может быть нулевым. Имя параметра: свойство.

Мой стиль в словаре ресурсов:

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

Проблема не в использованииResourceDictionary, так как, когда я удаляюWindowStartupLocation, два других свойства SizeToContent а такжеResizeMode) установлены, как и ожидалось, в окнах, которые ссылаются на стиль:

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

Кто-нибудь сталкивался с этим? Это ошибка / ограничение WPF?

P.S. Я знаю, что этот вопрос похож на Местоположение запуска Windows из словаря ресурсов, но по другому вопросу было предоставлено недостаточно информации, которая впоследствии осталась нерешенной.

Ответы на вопрос(2)

Решение Вопроса

что WindowStartupLocation не является DependencyProperty, поэтому вы не можете установить его в установщике стилей. Смотря в ILSpy Сеттер звонит

CheckValidProperty(DependencyProperty property)

и выбрасывает исключение NullArgumentException.

Поскольку WindowStartupLocation - это просто свойство CLR, его нельзя установить таким образом.

Edit: Чтобы ответить на комментарий. Вы все еще можете использовать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}" />
 User381062115 мая 2012 г., 12:08
Спасибо, самое полезное! К сожалению, я не могу использоватьStaticResource так как мне нужно сослаться наResourceDictionary отWindow (Я разрабатываю надстройку для Office, которая не предоставляет мне WPFApplication учебный класс). Но ваше предложение было бы замечательно для централизации стиля по умолчанию в приложениях Windows.
 User381062115 мая 2012 г., 10:36
Так что вам разрешено устанавливать свойство CLR (независимость) непосредственно из XAML (используя<Window WindowStartupLocation="CenterOwner" /> синтаксис), но не из словаря ресурсов, верно?
 Andrew Jones15 мая 2012 г., 10:40
Не совсем. Вы можете установить свойство непосредственно в XAML, но вы все равно можете использовать словарь ресурсов, но не стиль. То есть работает следующее: <Application.Resources> <ResourceDictionary> <Style x: Key = "WindowStyle" TargetType = "Window"> <Свойство Setter = "SizeToContent" Value = "WidthAndHeight" /> <Свойство Setter = "ResizeMode "Value =" CanMinimize "/> </ Style> <WindowStartupLocation x: Key =" WSL "> CenterOwner </ WindowStartupLocation> </ ResourceDictionary> </Application.Resources>

WindowStartupLocation является свойством CLR, это можно увидеть вILSpy:

[DefaultValue(WindowStartupLocation.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;
    }
}

В установщиках стилей можно указывать только свойство зависимости. Есть два способа решения этой проблемы:

наследовать класс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>
 Moumit17 дек. 2015 г., 11:58
Снимаю шляпу !! .. Это правильное решение

Ваш ответ на вопрос