2009-11-17 18 views
7

Recientemente he redefinido la cuadrícula DevXpress WPF para obtener una propiedad SelectedObject a la que puedo acceder desde mi ViewModel ligeramente enlazado.WPF ReadOnly Propiedades de dependencia usando MVVM

He hecho una propiedad de dependencia SelectedObject y lo tengo vinculado OneWayToSource en mi XAML.

Everthing funciona bien, pero si trato de hacerlo de forma ReadOnly (para completar) obtengo un error de compilación y dice que no puedo enlazar a una propiedad ReadOnly. El siguiente código compila, he incluido (pero eliminado) los bits que he estado intentando en mis intentos de obtener la propiedad ReadOnly.

¿Alguien puede ayudarme por favor?

la propiedad de dependencia de mi control reemplazado parece:

//public static readonly DependencyPropertyKey SelectedRowKey = DependencyProperty.RegisterReadOnly("SelectedObject", typeof(object), typeof(MyGrid), new PropertyMetadata(null)); 
//public static readonly DependencyProperty SelectedObjectProperty = SelectedRowKey.DependencyProperty; 

public readonly static DependencyProperty SelectedObjectProperty = DependencyProperty.Register("SelectedObject", typeof(object), typeof(MyGrid), new PropertyMetadata(null)); 

public object SelectedObject 
{ 
    get 
    { 

     return GetValue(SelectedObjectProperty); 
    } 
    set 
    { 
     throw new NotImplementedException(); 
    } 
} 

El XAML es:

<StackPanel> 
    <devxgrid:MyGrid AutoPopulateColumns="True" DataSource="{Binding Animals}" SelectedObject="{Binding MyObject, Mode=OneWayToSource}" Width="300" Height="300"> 
    <devxgrid:MyGrid.View> 
     <MyGrid:TableView AllowEditing="False" Name="GridView" AutoWidth="True" /> 
    </devxgrid:MyGrid.View> 
</devxgrid:MyGrid> 
</StackPanel> 

Respuesta

4

Usted está tratando de establecer la propiedad SelectedObject en el XAML. Si es de solo lectura, ¿cómo puedes configurarlo?

Editar: lo siento, mi mal. Solo me di cuenta de lo que estás tratando de hacer, y tienes razón en que debería funcionar. Sin embargo, WPF no admite este escenario, al menos en 3.5.

Editar 2: Acaba de registrarse en .NET 4 y la misma historia.

Por cierto, si está atrapado con el DP de solo lectura de alguien más que está tratando de "presionar" en una VM, puede utilizar un comportamiento adjunto para solucionar esto. Por ejemplo, supongamos que desea que su VM tenga conocimiento de las propiedades ActualWidth y ActualHeight de su vista. Puede escribir un SizeWatcherBehavior que se conecta al FrameworkElement y escucha los cambios de tamaño. Cuando se detecta, los cambios de tamaño son empujados para leer/escribir las propiedades asociadas que su máquina virtual se puede unir a:

<Grid local:SizeWatcherBehavior.Watch="True" 
    local:SizeWatcherBehavior.Width="{Binding WidthOnVM, Mode=OneWayToSource}" 
    local:SizeWatcherBehavior.Height="{Binding HeightOnVM, Mode=OneWayToSource}"/> 
+0

Gracias por su ayuda Kent - lamentablemente, no creo que pueda usar el observador en ningún lugar donde pueda usar DP, ¡pero es bueno saber que existen tales cosas! Mi programa funciona de todos modos, solo odio dejar eso 'throw new NotImplementedException();' - No es una "ventana rota", pero no está lejos. pero muchas gracias por investigarlo. –

+2

Creo que este es un problema grave con WPF y la adopción del patrón MVVM. Cuando la propiedad fuente es de solo lectura, se le permite definir enlaces OneWay, lo cual es genial. Pero cuando el DP objetivo es de solo lectura, no está permitido definir enlaces OneWayToSource. Realmente no entiendo por qué no ... – Oskar

+0

Y estoy realmente frustrado al escuchar que esto tampoco va a ser soportado en .NET 4. – Oskar

0

Estamos desarrollando una biblioteca de controles personalizados, y uno de nuestros usuarios presentaron una solicitud de función para convertir una de nuestras Los DP de solo lectura a lectura y escritura, porque sí tocó el mismo problema que usted, no pueden enlazar OneWayToSource en un escenario MVVM.

Por supuesto que no hicimos ese DP de lectura-escritura.

El uso de propiedades/comportamientos adjuntos para tales escenarios es una gran sobrecarga. La solución más simple sería manejar el evento "SelectedObjectChanged" en el código subyacente y establecer la propiedad que desea vincular al DP "SelectedObject" en el código subyacente.

En nuestra opinión, este enfoque de 'manejar el evento y el código de llamada desde VM/DataContext directamente' no rompe MVVM de ninguna manera, ya que ViewModel aún no sabe nada sobre la Vista.

+0

Obligar a las personas a escribir código detrás de intrínsecamente rompe mvvm. – DanH

4

Estoy un poco tarde a esta pregunta teniendo en cuenta que se le pidió hace casi 2 años :)

Hice una solución para ser dinámicamente capaz de empujar dependencia propiedades de sólo lectura a la fuente llamada PushBinding cual blogged about here .En su caso, se vería así

<devxgrid:MyGrid AutoPopulateColumns="True" 
       DataSource="{Binding Animals}" 
       Width="300" 
       Height="300"> 
    <pb:PushBindingManager.PushBindings> 
     <pb:PushBinding TargetProperty="SelectedObject" Path="MyObject"/> 
    </pb:PushBindingManager.PushBindings> 
    <!--...--> 
</devxgrid:MyGrid> 

PushBinding obras mediante el uso de dos propiedades de dependencia, Oyente y espejo. El oyente está vinculado OneWay a TargetProperty y en el PropertyChangedCallback actualiza la propiedad Mirror enlazada a OneWayToSource con lo que se especificó en el Enlace.

Demo Project can be Downloaded Here.
Contiene código fuente y uso de muestra breve, o visite my WPF blog si está interesado en los detalles de implementación.