当我尝试通过WindowStartupLocation
中的Setter
设置ResourceDictionary
属性时,我得到XamlParseException
:
'设置属性'System.Windows.Setter.Property'抛出异常。'行号'x'和行位置'y'。
内部异常是ArgumentNullException
:
值不能为空。参数名称:property。
我在资源词典中的风格是:
<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。我知道这个问题与Window Startup Location from resource dictionary类似,但在另一个问题中没有提供足够的信息,后来仍未解决。
答案 0 :(得分:10)
问题是WindowStartupLocation不是DependencyProperty,因此您无法在样式设置器中设置它。在ILSpy中查看Setter调用
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}" />
答案 1 :(得分:6)
WindowStartupLocation
是一个CLR属性,可以在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;
}
}
在样式设置器中只能指定依赖属性。有两种方法可以解决这个问题:
继承类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>