Wpf datacontext de liaison à l'aide de MVVM entre viewmodel et vue
J'ai juste commencé à apprendre le MVVM et voici ce qui semble être question de base mais j'ai passé toute la journée à essayer de le comprendre.
J'ai une solution qui contient 3 projets pour un Modèle, un pour le ViewModel et un pour la Vue. Le Modèle contient une classe qui possède 2 propriétés de Texte et CheckStatus.
Le ViewModel a une liste appelée listOfItems qui a trois éléments, chaque élément a ces 2 propriétés dans le Modèle.
Le point de Vue a une listView à l'intérieur il ya une Case à cocher. Quelle est la bonne façon de lier la Case contenu du Texte de la propriété?
Ici est le modèle
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TheModel
{
public class CheckBoxListModel : INotifyPropertyChanged
{
private string text;
public string Text
{
get { return text; }
set
{
text = value;
RaiseChanged("Text");
}
}
private bool checkStatus;
public bool CheckStatus
{
get { return checkStatus; }
set
{
checkStatus = value;
RaiseChanged("CheckStatus");
}
}
private void RaiseChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
Ici est le modèle de vue
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using TheModel;
namespace TheViewModel
{
public class TheViewModel
{
public List<CheckBoxListModel> ListOfItems { get; set; }
public TheViewModelClass()
{
ListOfItems = new List<CheckBoxListModel>
{
new CheckBoxListModel
{
CheckStatus = false,
Text = "Item 1",
},
new CheckBoxListModel
{
CheckStatus = false,
Text = "Item 2",
},
new CheckBoxListModel
{
CheckStatus = false,
Text = "Item 3",
}
};
}
public static implicit operator List<object>(TheViewModelClass v)
{
throw new NotImplementedException();
}
}
}
et voici la Vue XAML
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:TheView.Managers" xmlns:TheViewModel="clr-
namespace:TheViewModel;assembly=TheViewModel"
x:Class="TheView.Styles.ListViewDatabaseStyle">
<UserControl.DataContext>
<TheViewModel:TheViewModelClass/>
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Button Content="Continue" Style="{StaticResource ButtonStyle}"
Margin="1104,27,40,40"/>
<ListView x:Name="listView1" SelectionMode="Multiple"
Style="{StaticResource ListViewStyle}" Margin="10,55,10,10"
ctrl:ListViewLayoutManager.Enabled="true" ItemsSource="
{Binding TheViewModelClass}" >
<ListView.View>
<GridView>
<GridViewColumn Header="Competency Items"
ctrl:ProportionalColumn.Width="1100"/>
</GridView>
</ListView.View>
<ListView.ItemContainerStyle >
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding
CheckedStatus}"/>
<Setter Property="HorizontalContentAlignment"
Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox
Click="CheckBox_Click"
Content="{Binding Path=TheViewModelClass.Text}"
IsChecked="{Binding
Path=TheViewModelClass.CheckedStatus}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</UserControl>
Voici la Vue derrière le code, je sais que je ne devrais pas avoir quelque chose ici, mais où la partie de go?
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System;
using System.Text;
using TheViewModel;
namespace TheView.Styles
{
public partial class ListViewDatabaseStyle : UserControl
{
public ListViewDatabaseStyle()
{
InitializeComponent();
}
public List<string> selectedNames = new List<string>();
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
var ChkBox = sender as CheckBox;
var item = ChkBox.Content;
bool isChecked = ChkBox.IsChecked.HasValue ? ChkBox.IsChecked.Value
: false;
if (isChecked)
selectedNames.Add(item.ToString());
else
selectedNames.Remove(item.ToString());
}
}
}
Je n'ai pas trouvé la bonne façon d'utiliser le DataContext de sorte que cela fonctionne. J'ai essayé plusieurs fois et je l'ai vu mis en œuvre dans plusieurs sens, mais aucun n'a fonctionné pour moi
partie supprimée du derrière le code pour le datacontext parce que c'était le mal par. et désolé @Peter votre solution n'a pas fonctionné
Si j'étais vous, je voudrais changer de liste pour ObservableCollection. public ObservableCollection<CheckBoxListModel> ListOfItems { get; set; } Et faites-moi confiance. Vous n'avez pas à ajouter chaque liaison de votre viewmodel. Dans votre Listview ItemSource={Binding ListOfItems} <Case Content="{Binding Texte}" IsChecked="{Binding CheckedStatus}" />
En passant, vous pouvez trouver de l'aide dans le WPF salle de chat. Nous sommes là, la plupart des jours de la semaine pendant les heures de travail.
OriginalL'auteur | 2017-04-26
Vous devez vous connecter pour publier un commentaire.
Tout d'abord. Définir les dépendances de projets. ViewModel doit avoir accès au Modèle. (Modèle et de la vue projets n'ont pas de référence à d'autres projets.) Si j'étais vous, je voudrais faire un Projet de Démarrage pour transférer le contrôle à ViewModel.
Ce "Démarrage" projet devrait être WPF, tous les autres devraient être la "bibliothèque de classes", mais n'oubliez pas d'ajouter les références nécessaires aux projets (Par exemple le système.xaml pour votre vision de projet pour créer des usercontrols.)
Projets de dépendances:
- Démarrage --> ViewModel;
(- ViewModel --> Affichage; ou d'éviter cela avec DI)
- ViewModel --> Modèle;
(Je devrais faire un autre projet pour les interfaces juste c'est juste mon perversions.)
Projet De Démarrage:
Maintenant, dans votre démarrage (WPF) projet devrait contient (app.xaml.cs):
La seule chose (Fenêtre) dans votre démarrage du projet wpf (pour afficher votre UserControls).
MainWindow.contenu xaml:
(et xaml.cs)
Et c'est tout votre Démarrage du projet WPF.
De cette façon, nous a donné le contrôle de votre Dernier projet.
(Bon d'accord, c'est juste un extra, mais je devrais faire un "ViewService" gérer mon UserControls)
Interface pour retrouver l'ensemble de la Vue et de la correspondance de la Vue avec ViewModel.
J'ai créé un singleton pour stocker et correspond à mes opinions avec mon viewmodel. (Vous pouvez sauter cette partie.) J'ai défini ce dans Modèle projet.
Et maintenant, vous avez un "service" pour montrer votre UserControls dans la mainwindow à partir de votre
ViewModel:
Si vous ne souhaitez pas utiliser cette "ViewService". Il suffit de créer un UserControl exemple, correspondre à DataContext de la Vue avec votre ViewModel et donner ce point de vue pour le Contrôle de la propriété.
Ici est votre ViewModel avec la liste (toujours dans ViewMoldel projet.)
RelayCommand article
Vue: (Garder ici toutes vos usercontrols.)
Dans votre UserControl (xaml):
Et avec interface voici le code xaml.cs code (pour les contrôles utilisateur):
Et le dernier est le Modèle projet avec vos modèles:
Excusez-moi pour l'anglais, la grammaire des fautes, j'espère que vous avez compris mon post.
Mise à jour:
Utiliser le DI techn. afin d'éviter la référence à la vue du viewmodel. DI service va injecter de l'objet avec un constructeur d'injection.
petite question, le ViewService et le singleton vous l'avez mentionné, où devrait-il être créé?
J'ai défini ce dans le Modèle de Projet. En raison des dépendances vous pouvez l'utiliser n'importe où dans votre Dernier projet.
Ainsi, le "ViewService", le "IControlView" et "ISelectable" font-ils partie de la bibliothèque de classe appelé "Modèle" du fichier, ou de séparer les classes à l'intérieur de la bibliothèque de classe? si vous savez ce que je veux dire
J'ai fait un autre projet pour les interfaces et tous les projets ont accès à cette interface projet. Ainsi, vous pouvez définir l'ensemble de vos interfaces séparée de ce projet. De cette façon IControlView et ISelectable dans les Interfaces du projet et ViewService classe dans le Modèle de projet. Par la façon dont de projet "bibliothèque de classes" type (à l'exception du Démarrage du projet WPF).
OriginalL'auteur Péter Hidvégi
Mais c'est la façon dont il devrait fonctionner. Le problème n'est probablement pas dans votre xaml, mais le code que vous n'avez pas montré. Je vois que vous avez manipulé avec le code lors de la copie&coller ici, car il y a des erreurs dans votre viewmodel. Tant pis, c'est la bonne façon de le faire. Vérifiez votre Sortie de windows lors du débogage de l'application. BTW, n'avez-vous pas modifié le ControlTemplate de Case?
oui, j'ai modifié et oui le code est différent parce que je suis en train de travailler sur une copie. nous espérons qu'avec un peu d'aide, je vais être en mesure de comprendre pourquoi ça ne fonctionne pas 🙂 merci à tous
OriginalL'auteur Liero