2009-11-17 11 views
7

J'ai récemment remplacé la grille DevXpress WPF pour me donner une propriété SelectedObject que je peux accéder à partir de ma ViewModel lâche.WPF ReadOnly propriétés de dépendance utilisant MVVM

J'ai créé une propriété de dépendance SelectedObject et l'ai liée à OneWayToSource dans mon code XAML.

Everthing fonctionne très bien, mais si j'essaye de le faire ReadOnly (pour l'exhaustivité) j'obtiens une erreur de compilation et dit que je ne peux pas me lier à une propriété ReadOnly. Le code ci-dessous compile, j'ai inclus (mais j'ai supprimé) les bits que j'ai essayés dans mes tentatives pour obtenir la propriété ReadOnly.

Quelqu'un peut-il vous aider s'il vous plaît?

La propriété de dépendance de mon contrôle surchargée ressemble:

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

Le XAML est:

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

Répondre

4

Vous essayez de définir la propriété SelectedObject dans le XAML. Si c'est en lecture seule, comment pouvez-vous le définir?

Edit: désolé, mon mauvais. Je viens de réaliser ce que vous essayez de faire, et vous avez raison de dire que cela devrait fonctionner. Cependant, WPF ne supporte pas ce scénario, au moins en 3.5.

Édition 2: Juste vérifié dans .NET 4 et même histoire. A propos, si vous êtes coincé avec le DP en lecture seule de quelqu'un d'autre que vous essayez de "pousser" dans une machine virtuelle, vous pouvez utiliser un comportement ci-joint pour contourner ce problème. Par exemple, supposons que vous souhaitiez que votre machine virtuelle soit consciente des propriétés ActualWidth et ActualHeight de votre vue. Vous pouvez écrire un SizeWatcherBehavior attaché au FrameworkElement et à l'écoute des changements de taille. Lorsqu'il est détecté, ces changements de taille sont poussés à lire/écrire des propriétés attachées que votre machine virtuelle peut se lier à:

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

Merci pour votre aide Kent - malheureusement, je ne pense pas que je peux utiliser l'observateur à theres aucun DP à utiliser, mais il est bon de savoir que de telles choses existent! Mon programme fonctionne de toute façon, je déteste juste quitter 'throw new NotImplementedException();' - Ce n'est pas une «fenêtre brisée» mais ce n'est pas loin! mais merci beaucoup d'y avoir réfléchi. –

+2

Je pense que c'est un problème sérieux avec WPF et l'adoption du modèle MVVM. Lorsque la propriété source est en lecture seule, vous êtes autorisé à définir les liaisons OneWay, ce qui est génial. Mais quand le DP cible est en lecture seule, vous n'êtes pas autorisé à définir les liaisons OneWayToSource. Je ne comprends pas vraiment pourquoi pas .. – Oskar

+0

Et je suis vraiment frustré d'entendre que cela ne va pas être pris en charge dans .NET 4 non plus. – Oskar

0

Nous développons une bibliothèque de contrôle personnalisé, et un de nos utilisateurs ont déposé une demande de fonctionnalité pour convertir un de nos Les DP de Read-Only à Read-Write, parce qu'il a rencontré le même problème que vous, ne peuvent pas lier OneWayToSource dans un scénario MVVM.

Bien sûr, nous n'avons pas fait ce DP en lecture-écriture. L'utilisation de propriétés/comportements attachés pour de tels scénarios représente un énorme temps système. La solution de contournement la plus simple consisterait à gérer l'événement "SelectedObjectChanged" dans le code derrière, et définir la propriété que vous vouliez lier à "SelectedObject" DP dans le code derrière. À notre avis, cette approche «gérer l'événement et le code d'appel de VM/DataContext directement» ne rompt en aucun cas MVVM, puisque le ViewModel ne sait toujours rien de la vue.

+0

Forcer les gens à écrire du code derrière les pauses instructive mvvm. – DanH

4

Je suis un peu en retard à cette question étant donné qu'il a été posée il y a presque 2 ans :)

J'ai fait une solution pour être en mesure de pousser dynamiquement en lecture seule dépendance des propriétés à la source appelée PushBinding que je blogged about here .Dans votre cas, il ressemblerait à ce

<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 fonctionne en utilisant deux propriétés de dépendance, Listener et miroir. Listener est lié OneWay à TargetProperty et dans le PropertyChangedCallback il met à jour la propriété Mirror qui est liée OneWayToSource à tout ce qui a été spécifié dans la liaison.

Demo Project can be Downloaded Here.
Il contient le code source et l'utilisation de l'échantillon court, ou visitez my WPF blog si vous êtes intéressé par les détails de mise en œuvre.

Questions connexes