UserControls et viewmodel en Vue de la Première MVVM

Je suis obligé d'utiliser d'Abord la Vue de MVVM dans une application WPF et j'ai du mal à voir comment il peut être fait de travailler en toute élégance.

La racine du problème se trouve avec imbriqué UserControls. Dans une architecture MVVM chaque UserControl a besoin d'avoir son point de vue, le modèle attribués à ses DataContext, ce qui maintient les expressions de liaison simple, et en plus c'est aussi un moyen de WPF pour instancier une vue générée par DataTemplate.

Mais si un enfant UserControl a des propriétés de dépendance dont le parent a besoin de se lier à son propre viewmodel puis, le fait que l'enfant UserControl a son DataContext réglé à sa propre viewmodel signifie qu'une "implicite" chemin de liaison dans le parent de fichier XAML permettra de résoudre à l'enfant du viewmodel au lieu de celle du parent.

Pour contourner ce tous les parents de tous les UserControl dans l'application aura besoin d'utiliser explicitement nommé liaisons pour tout par défaut (qui est verbeux, moche et susceptible de causer des erreurs), ou qu'il va avoir à savoir si un contrôle spécifique a son DataContext réglé à sa propre viewmodel ou pas et d'utiliser la syntaxe de liaison, (qui est également susceptible de causer des erreurs, et une grave violation de base de l'encapsulation).

Après des jours de recherche je n'ai pas rencontré un seul demi décent solution à ce problème. La chose la plus proche à une solution que j'ai trouver est le réglage de la UserControl's viewmodel à l'intérieure d'un élément de la UserControl (le plus haut Grid ou quoi que ce soit), ce qui laisse tout de même vous face à un problème en essayant de lier les propriétés de la UserControl lui-même à ses propres viewmodel! (ElementName de liaison ne fonctionne pas dans ce cas, parce que la liaison puisse être déclaré avant le nom de l'élément avec le viewmodel affecté à sa DataContext).

Je soupçonne que la raison de ne pas beaucoup d'autres personnes ce qu'ils sont soit à l'aide viewmodel première MVVM qui n'ont pas ce problème, ou qu'ils utilisent d'abord la vue de MVVM en conjonction avec une injection de dépendance de la mise en œuvre que amelliorates cette question.

Quelqu'un aurait-il une solution propre pour cela, s'il vous plaît?

Mise à JOUR:

Exemple de code comme demandé.

<!-- MainWindow.xaml -->
<Window x:Class="UiInteraction.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:UiInteraction"
        Title="MainWindow" Height="350" Width="525"
        x:Name="_this">

    <Window.DataContext>
        <local:MainWindowVm/>
    </Window.DataContext>

    <StackPanel>
        <local:UserControl6 Text="{Binding MainWindowVmString1}"/>  
    </StackPanel>

</Window>
namespace UiInteraction
{
    //MainWindow viewmodel.
    class MainWindowVm
    {
        public string MainWindowVmString1
        {
            get { return "MainWindowVm.String1"; }
        }
    }
}
<!-- UserControl6.xaml -->
<UserControl x:Class="UiInteraction.UserControl6" x:Name="_this"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:local="clr-namespace:UiInteraction">

    <UserControl.DataContext>
        <local:UserControl6Vm/>
    </UserControl.DataContext>

    <StackPanel>
        <!-- Is bound to this UserControl's own viewmodel. -->
        <TextBlock Text="{Binding UserControlVmString1}"/>

        <!-- Has its value set by the UserControl's parent via dependency property. -->
        <TextBlock Text="{Binding Text, ElementName=_this}"/>
    </StackPanel>

</UserControl>
namespace UiInteraction
{
    using System.Windows;
    using System.Windows.Controls;

    //UserControl code behind declares DependencyProperty for parent to bind to.
    public partial class UserControl6 : UserControl
    {
        public UserControl6()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
            "Text", typeof(string), typeof(UserControl6));

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
    }
}
namespace UiInteraction
{
    //UserControl's viewmodel.
    class UserControl6Vm
    {
        public string UserControlVmString1
        {
            get { return "UserControl6Vm.String1"; }
        }
    }
}

Il en résulte:

Système.De Windows.Erreur de données: 40 : BindingExpression erreur de chemin d'accès:
'MainWindowVmString1 biens ne se trouvent pas sur l '"objet" "UserControl6Vm'
(HashCode=44204140)'. BindingExpression:Path=MainWindowVmString1;
DataItem='UserControl6Vm' (HashCode=44204140); élément cible est
'UserControl6' (Nom='_ce'); cible de la propriété est de "Texte" (type
'String')

parce que dans MainWindow.xaml la déclaration <local:UserControl6 Text="{Binding MainWindowVmString1}"/> est de tenter de résoudre MainWindowVmString1 sur UserControl6Vm.

Dans UserControl6.xaml en commentant la déclaration de la DataContext et la première TextBlock le code fonctionne, mais le UserControl besoin d'un DataContext. Dans MainWIndow1 à l'aide d'un ElementName au lieu d'une implict chemin de liaison, mais pour utiliser la ElementName syntaxe de liaison vous devez savoir que la UserControl assigne son viewmodel à son DataContext (encapsulation échec) ou altenatively adopter une politique sur l'utilisation ElementName liaisons partout. Ni de ce qui est attrayant.

Pouvez-vous donner un exemple de code? Avez-vous regardé l'Application WPF Cadre fourni par Microsoft? L'imbrication Viewmodel est un problème commun.
Je sais que cette question est un peu vieux et juste heurté par la Communauté, mais les cités approche de "UserControl's viewmodel à l'intérieur de l'élément" doit être la solution. Je serais intéressé de voir des exemples où une liaison de l'objet UserControl propriétés pour le viewmodel est nécessaire typique UserControl paramètres sont purement de l'INTERFACE utilisateur de choses se rapportant à ou devrait être mis sur l'utilisation plutôt que de la déclaration.
Tout UserControl qui accède à des non-trivial de données ou de configuration aurez souvent besoin d'avoir ses contrôles liés à son viewmodel. E. g. un widget réglages, ou l'affichage des données du widget. Seuls les plus trival composants de l'INTERFACE utilisateur ont pas de connexion à un modèle de données sous-jacente à tous, par exemple, un bouton où le texte du bouton est définie par l'intermédiaire de la propriété de dépendance obligatoire dans l'INTERFACE utilisateur.

OriginalL'auteur Neutrino | 2013-01-21