2012-05-15 14 views
7

Cuando intento para establecer la propiedad a través de un WindowStartupLocationSetter dentro de un ResourceDictionary, consigo un XamlParseException:Configuración WindowStartupLocation de ResourceDictionary tiros XamlParseException

'Establecer la propiedad 'System.Windows.Setter.Property' produjo una excepción . ' El número de línea 'x' y la posición de línea 'y'.

la excepción interna es un ArgumentNullException:

valor no puede ser nulo. Nombre del parámetro: propiedad.

Mi estilo dentro del diccionario de recursos es:

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

El problema no es con el uso de la ResourceDictionary, ya que cuando se quita la WindowStartupLocation, se establecen las otras dos propiedades (SizeToContent y ResizeMode) como se esperaba en las ventanas que hacen referencia al estilo:

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

¿Alguien ha encontrado esto? ¿Es un error/limitación de WPF?

P.S. Sé que esta pregunta es similar a Window Startup Location from resource dictionary, pero no se proporcionó suficiente información en la otra pregunta que posteriormente quedó sin resolver.

Respuesta

8

El problema es que WindowStartupLocation no es DependencyProperty, por lo que no puede establecerlo en el conjunto de estilos. Buscando en ILSpy el Setter llama al

CheckValidProperty(DependencyProperty property) 

y arroja una NullArgumentException.

Como WindowStartupLocation es solo una propiedad de CLR, no se puede establecer de esta manera.

Edit: Responder al comentario. Todavía se puede utilizar un 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}" /> 
+0

Entonces se le permite establecer un CLR (no-dependencia) Propiedad directamente de XAML (usando ' 'sintaxis), pero no de un diccionario de recursos, ¿correcto? – User3810621

+0

No del todo. Puede establecer la propiedad directamente en XAML, pero aún puede usar un diccionario de recursos, pero no el Estilo. Es decir, los siguientes trabajos: CenterOwner

+0

Gracias, muy útil! Lamentablemente, no puedo usar 'StaticResource' ya que necesito hacer referencia al' ResourceDictionary' desde 'Window' (estoy desarrollando un complemento de Office que no me da una clase' Application' de WPF). Pero su sugerencia sería genial para centralizar el estilo predeterminado en las aplicaciones de Windows. – User3810621

5

WindowStartupLocation es una propiedad CLR, esto se puede ver en 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; 
    } 
} 

En los emisores de estilo sólo se puede especificar propiedad de dependencia. Hay dos maneras de resolver este problema:

  • clase hereda Window, y crear su clase con una propiedad de dependencia WindowStartupLocation

  • crear un tipo de propiedad adjunta dependiendo WindowStartupLocation y definir la lógica en el PropertyChanged

El primer método es engorroso, porque es necesario redefinir la clase para una propiedad. Se prefiere el segundo método, y se adjuntará el comportamiento, pero voy a llamar al PropertyExtension.

Aquí está el código completo:

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); 
      } 
     } 
    } 
} 

Ejemplo de uso:

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

¡Felicitaciones! .. Esa es una solución adecuada :) – Moumit

Cuestiones relacionadas