2013-07-07 5 views
1

J'allais créer cela avec des formulaires Windows, mais on m'a dit que wpf mvvm serait mieux. Je suis nouveau à C# et j'ai fait des recherches sur mvvm et wpf.MVVM ViewModel création et liaison

Je travaille actuellement sur mon viewmodel pour travailler avec la vue et le modèle. Il n'y a pas de base de données.


Mon problème:

comment puis-je lie correctement la vue sur la viewmodel. Il me manque un code itemsource ou localsource quelque part dans mon xaml mais je ne comprends pas non plus le fonctionnement de l'itemource. Où dans le viewmodel est l'itemource déclaré et comment. J'ai été googling pour une bonne réponse mais n'ai toujours pas trouvé un qui le fait cliqueter pour moi.

Je sais aussi qu'il y a une propriété de type INotifyChange et j'ai vu quelques exemples de code mais je ne comprends pas tout à fait, il n'a pas cliqué sur moi.


Actuellement:

J'ai une vue créée en XAML qui est le premier code ci-dessous. J'ai ensuite créé une classe pour un scan qui est le deuxième groupe de code ci-dessous dans C# (je sais que les méthodes get set pourraient être améliorées mais je suivais un tutoriel).

L'utilisateur avec le pistolet de balayage ne regardera pas l'écran pendant la numérisation. Je veux être en mesure d'aller dans l'ordre afin que la première numérisation remplisse la première zone de texte, la deuxième numérisation remplisse la deuxième zone de texte et si nécessaire, elle remplira le nombre.


Extra info:

La partie inférieure (DATAVIEW) est une table temporaire pour montrer les analyses précédentes, mais je peux comprendre que notre plus tard. La partie la plus importante est d'être en mesure d'obtenir les scans et de faire quelque chose avec eux. Les scans seront keyboardwedge (envoie des caractères comme étant tapé avec une touche d'entrée à la fin) mais plus tard, je prévois de les faire passer en série afin que ce programme puisse fonctionner en arrière-plan. Remarque: Je sais que j'ai donné beaucoup de détails qui ne sont probablement pas nécessaires pour le petit problème actuel, mais je voulais juste être clair.

<Window x:Class="ScanningV2.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="700"> 
    <DockPanel LastChildFill="True"> 
     <Grid x:Name="LayoutRoot" DockPanel.Dock="Top" Height="100" Background="#FFFFFF" Margin="2,2,2,2"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="*"></RowDefinition> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="150"></ColumnDefinition> 
       <ColumnDefinition Width="*"></ColumnDefinition> 
      </Grid.ColumnDefinitions> 
      <Button Grid.Row="0" Grid.Column="0" Content="Scan" Grid.ColumnSpan="1" Margin="2,2,2.2,2" /> 
      <Label Content="Operator Barcode" Grid.Column="1" HorizontalAlignment="Left" Margin="50,20,0,0" VerticalAlignment="Top" Width="120" /> 
      <Label Content="MO/Task Barcode" Grid.Column="1" HorizontalAlignment="Left" Margin="200,20,0,0" VerticalAlignment="Top" Width="120" /> 
      <Label Content="Quantity" Grid.Column="1" HorizontalAlignment="Left" Margin="350,20,0,0" VerticalAlignment="Top" Width="120" /> 
      <TextBox Grid.Column="1" HorizontalAlignment="Left" Margin="50,50,0,0" TextWrapping="Wrap" Text="Scan" VerticalAlignment="Top" Height="20" Width="120" /> 
      <TextBox Grid.Column="1" HorizontalAlignment="Left" Margin="200,50,0,0" TextWrapping="Wrap" Text="Scan" VerticalAlignment="Top" Height="20" Width="120" /> 
      <TextBox Grid.Column="1" HorizontalAlignment="Left" Margin="350,50,0,0" TextWrapping="Wrap" Text="Scan" VerticalAlignment="Top" Height="20" Width="120" /> 

      <!--   <ListView Grid.Row="0" Grid.Column="1" x:Name="curScans" Background="Aqua" Grid.ColumnSpan="1" Margin="1.8,0,-0.4,0"> 
       <ListView.View> 
        <GridView> 
         <GridViewColumn Header="Scanner" DisplayMemberBinding="{Binding Path=curScanNum}" Width="150" /> 
         <GridViewColumn Header="Operator" DisplayMemberBinding="{Binding Path=curOperator}" Width="200" /> 
         <GridViewColumn Header="Task" DisplayMemberBinding="{Binding Path=curTask}" Width="200"/> 
        </GridView> 
       </ListView.View> 
      </ListView> --> 
     </Grid> 
     <ListView x:Name="pastScans" Background="#2FFFFFFF" DockPanel.Dock="Bottom"> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="Scanner" DisplayMemberBinding="{Binding Path=ScannerNum}" Width="100" /> 
        <GridViewColumn Header="Operator barcode" DisplayMemberBinding="{Binding Path=Operator}" Width="150" /> 
        <GridViewColumn Header="MO/Task barcode" DisplayMemberBinding="{Binding Path=Task}" Width="150" /> 
        <GridViewColumn Header="Date" DisplayMemberBinding="{Binding Path=ScanDate}" Width="100" /> 
        <GridViewColumn Header="Time" DisplayMemberBinding="{Binding Path=ScanTime}" Width="100" /> 
        <GridViewColumn Header="Quantity" DisplayMemberBinding="{Binding Path=Quantity}" Width="100" /> 
       </GridView> 
      </ListView.View> 
     </ListView> 

    </DockPanel> 

</Window> 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ScanningV2 
{ 
    class scan 
    { 
     //Member variables 
     private string operatorCode; 
     public string OperatorCode 
     { 
      get { return operatorCode; } 
      set { operatorCode = value; } 
     } 

     private string taskCode; 
     public string TaskCode 
     { 
      get { return taskCode; } 
      set { taskCode = value; } 
     } 

     private int count; 
     public int Count 
     { 
      get { return count; } 
      set { count = value; } 
     } 

     private DateTime scanDateTime; 
     public DateTime ScanDateTime 
     { 
      get { return scanDateTime; } 
      set { scanDateTime = value; } 
     } 

     //Default Constructor 
     public scan() 
     { 
      operatorCode = null; 
      taskCode = null; 
      count = 0; 
     } 

     //Overload Constructor 
     public scan(string OperCode, string TaskMOCode, int CountNum) 
     { 
      operatorCode = OperCode; 
      taskCode = TaskMOCode; 
      count = CountNum; 
     } 
    } 
} 
+0

Votre classe d'analyse doit hériter de INotifyPropertyChanged et chaque instance doit se trouver dans une collection observable. C'est la collection observable qui doit être créée dans votre machine virtuelle et liée à la propriété de source d'élément du contrôle ListView. Obtenir l'extrait de génération de propriété C# sauvera votre LIFE en termes de refactorisation de votre classe 'scan'! –

Répondre

0

Vous devrez définir une instance de votre classe view-model en tant que DataContext de votre vue. Je fais habituellement cela dans le code-behind de vue, donc dans vos MainWindow.xaml.cs vous procédez comme suit:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     DataContext = new Scan(); 
    } 
} 

Gardez à l'esprit que votre vue ne sera pas en mesure de détecter les changements à moins que vous notifie-le.C'est le point de l'interface INotifyPropertyChanged:

class Scan : INotifyPropertyChanged 
{ 
    // Implementing the INotifyPropertyChanged interface: 
    public event PropertyChangedEventHandler PropertyChanged; 

    // A utility method to make raising the above event a little easier: 
    protected void RaisePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    // Then, notify the view about changes whenever a property is set: 
    private string operatorCode; 
    public string OperatorCode 
    { 
     get { return operatorCode; } 
     set { operatorCode = value; RaisePropertyChanged("OperatorCode"); } 
    } 
} 

Dans votre MainWindow.xaml, vous pouvez lier à cette propriété:

<TextBlock Text="{Binding OperatorCode}" /> 

Maintenant, chaque fois que vous définissez une nouvelle valeur pour OperatorCode, votre vue sera notifié afin qu'il puisse récupérer et afficher la nouvelle valeur. Pour ItemsSources, tout IEnumerable fera - une Liste, un tableau ... cependant, si vous voulez que la vue soit notifiée chaque fois que votre collection change, vous devrez utiliser une classe qui implémente INotifyCollectionChanged, comme ObservableCollection .

Ainsi, vous créez une propriété liable dans votre vue-modèle:

private ObservableCollection<string> names; 
public ObservableCollection<string> Names 
{ 
    get { return names; } 
    set { names = value; RaisePropertyChanged("Names"); } 
} 

Et vous liez à celle de l'intérieur de votre vue:

<ListView ItemsSource="{Binding Names}" /> 

point mineur: en C#, les noms de classe sont généralement écrit en CamelCase. Personnellement, je préfère donner à chaque classe de modèle de vue un suffixe ViewModel, afin que vous puissiez rapidement voir quelles classes sont censées être des modèles de vues. J'essaie de faire correspondre leur nom avec le nom de la vue à laquelle ils appartiennent, donc au lieu de 'scan', je l'appellerais 'MainWindowViewModel'.

+0

Pieter, merci, c'est un excellent point de départ. Beaucoup de vos petits commentaires ont rassemblé ce qui me manquait dans la plupart des autres lectures. – BrinkDaDrink

0

Vous ne pouvez pas lier tout cela à tous les éléments de l'interface utilisateur WPF parce que votre code est trop comme java. Vous devez utiliser Properties le chemin C#.

changez toutes vos méthodes get() et set() en propriétés réelles.

+0

Merci HighCore pour le début. Je les ai changé correctement je crois. – BrinkDaDrink

Questions connexes