Ich möchte mit Ihnen dieses Beispielprojekt als eine einfache Demonstration der Verwendung von MVVM mit Sammlungen teilen. Ich hoffe, Sie finden es nützlich.
Also, das erste, was Sie tun möchten, ist eine ObservableObject
Klasse zu definieren, die Ihnen Zugriff auf INotifyPropertyChanged
ermöglicht. Dies ist eine sehr einfache Implementierung, aber es wird in den meisten Situationen gut funktionieren.
using System.ComponentModel;
namespace WpfApplication8
{
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
Wir werden dies aus unserer Sicht-Modell implementieren, sowie alle benutzerdefinierten Typen möchten wir INotifyPropertyChanged
nutzen.
Diese Demo verwendet eine Klasse Book
. Die Book
Klasse wird einfach ein paar Felder enthalten, und wir werden auch eine ICommand
Implementierung in die gleiche Datei aufnehmen, um das Binden später zu erleichtern.Immer wenn ein ICommand
speziell für einen Type
gilt, verwende ich gerne die Codedatei dieses Type
, um die Dinge sauber gruppiert zu halten.
using System;
using System.Windows.Input;
namespace WpfApplication8
{
public class Book : ObservableObject
{
private string _title = "";
public string Title
{
get
{
return _title;
}
set
{
_title = value;
RaisePropertyChanged("Title");
}
}
private string _author = "";
public string Author
{
get
{
return _author;
}
set
{
_author = value;
RaisePropertyChanged("Author");
}
}
}
public abstract class BookCommand : ICommand
{
public abstract void Execute(object parameter);
public virtual bool CanExecute(object parameter)
{
return parameter is Book;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
Als nächstes werden wir eine ObservableCollection
Implementierung benötigen, die uns die volle Kontrolle über das gibt, was geschieht, wenn ein Objekt hinzugefügt oder entfernt wird. Wir wollen auch ICommand
Objekte zum Hinzufügen von Büchern entfernen.
Das mag auf den ersten Blick überwältigend erscheinen, aber wenn man es Schritt für Schritt abbricht, ist es nicht so schlimm. Das Ereignis CollectionChanged
gibt uns die Möglichkeit, benutzerdefinierte Funktionen hinzuzufügen, wenn ein Element zur Sammlung hinzugefügt oder aus dieser entfernt wird. Dies macht es zum Beispiel recht einfach, ein neues Element aus der Liste auszuwählen, nachdem etwas entfernt wurde. Wir haben auch eine BookCollectionCommand
abstrakte Klasse als Grundlage für unsere konkreten ICommand
Implementierungen erstellt. Der Grund dafür liegt in der Reduzierung der Redundanz, die je nach Projekt nicht ideal ist, aber hier funktioniert es ganz gut.
Das nächste, was wir brauchen, ist ein Root View-Modell, das direkt an unsere Sicht gebunden ist.
Beachten Sie das Feld NewBookTemplate
. Sie haben sich vielleicht gewundert, warum ich den Parameter CMD_AddBookToCollection
nicht direkt in die Sammlung geschoben habe. Der Parameter in diesem Muster ist nur eine Vorlage, ein Wegwerfobjekt, das zum Übergeben von Eingaben aus der Ansicht in das Ansichtsmodell verwendet wird. Dies gibt uns zwei sehr wichtige Freiheiten: Wir können das Objekt säubern, bevor es in unsere Sammlung übergeben wird, und wir können vermeiden, ein spezielles Ansichtsmodell nur für das Formular "ein neues Buch hinzufügen" zu schreiben. Die Klasse Book
selbst kann als Ansichtsmodell fungieren, was uns sowohl Arbeit spart als auch uns die Freiheit gibt, dieses Objekt in jeder anderen Ansicht wiederzuverwenden. Alles, was wir jetzt brauchen, ist eine grundlegende Ansicht zu implementieren und dies alles zu testen.
<Window x:Class="WpfApplication8.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication8"
x:Name="main_window"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<StackPanel.Resources>
<Style TargetType="FrameworkElement" x:Key="default_styles">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="30" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="5" />
</Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource default_styles}" >
<Setter Property="Width" Value="50" />
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource default_styles}" />
<Style TargetType="Button" BasedOn="{StaticResource default_styles}" />
</StackPanel.Resources>
<TextBlock Text="Title: " />
<TextBox Text="{Binding NewBookTemplate.Title, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="Author: " />
<TextBox Text="{Binding NewBookTemplate.Author, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Add Book " Command="{Binding MyBooks.AddBook}" CommandParameter="{Binding NewBookTemplate}" />
<Button Content="Remove Book " Command="{Binding MyBooks.RemoveBook}" CommandParameter="{Binding MyBooks.SelectedItem}" />
<TextBlock Text="Count: " />
<TextBlock Text="{Binding MyBooks.Count}" />
</StackPanel>
<ListBox Grid.Row="1" ItemsSource="{Binding MyBooks}" SelectedItem="{Binding MyBooks.SelectedItem, UpdateSourceTrigger=PropertyChanged}" >
<ListBox.InputBindings>
<KeyBinding Key="Delete" Command="{Binding MyBooks.RemoveBook}" CommandParameter="{Binding MyBooks.SelectedItem}" />
</ListBox.InputBindings>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<TextBlock Text=", " />
<TextBlock Text="{Binding Author}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Nun, alles funktioniert auf meinem Ende. Ich hoffe, dieses Beispiel hilft, MVVM
etwas leichter zu verdauen. Glückliche Kodierung!
Sie können "Auswahl" -Logik in den Setter der Items-Eigenschaft von ViewModel einfügen. Jedes Mal, wenn eine neue Liste gesetzt wird, wird Ihr 'SelectedItem' aktualisiert. – Fabio