Freigeben über


Erstellen einer einfachen Datenanwendung mit WPF und Entity Framework 6

Hinweis

Wenn Sie Visual Studio 2022 ausführen, stellen Sie sicher, dass Sie Version 17.3 oder höher für dieses Lernprogramm verwenden.

In diesem Lernprogramm wird gezeigt, wie Sie in Visual Studio eine einfache Formulare über Daten Anwendung erstellen. Die App verwendet SQL Server LocalDB, die Northwind-Datenbank, Entity Framework 6 (nicht Entity Framework Core) und Windows Presentation Foundation (WPF) für .NET Framework (nicht .NET Core oder .NET 5 oder höher). Es zeigt, wie Sie grundlegende Datenbindung mit einer Master-Detail-Ansicht durchführen, die ein benutzerdefiniertes BindingNavigator-Steuerelement mit Schaltflächen enthält, die die folgenden Aktionen ausführen: Zum ersten Element wechseln, vorheriges, nächstes, letztes Element wechseln, löschen, hinzufügen, neue Reihenfolge festlegen, aktualisieren und abbrechen.

Dieses Lernprogramm konzentriert sich auf die Verwendung von Datentools in Visual Studio und versucht nicht, die zugrunde liegenden Technologien ausführlich zu erläutern. Es wird davon ausgegangen, dass Sie mit Extensible Application Markup Language (XAML), Entity Framework und SQL vertraut sind. Obwohl der Code in diesem Lernprogramm keine Model-View-ViewModel (MVVM)-Architektur veranschaulicht, die für WPF-Anwendungen standard ist, können Sie den Code mit einigen Änderungen in Ihre eigene MVVM-Anwendung kopieren.

Um den endgültigen Code für dieses Lernprogramm anzuzeigen, sehen Sie sich die Visual Studio-Lernprogrammbeispiele - EF6 an.

In diesem Tutorial erfahren Sie:

  • Installieren und Herstellen einer Verbindung mit Northwind
  • Konfigurieren des WPF-App-Projekts
  • Erstellen des ADO.NET Entitätsdatenmodells
  • Datenbindung des Modells an die XAML-Seite
  • Anpassen des Seitenentwurfs und Hinzufügen von Rastern
  • Hinzufügen von Schaltflächen zum Navigieren, Hinzufügen, Aktualisieren und Löschen
  • Ausführen der WPF-Anwendung

Voraussetzungen

  • Visual Studio mit installierter .NET Desktop Development-Workload und der installierten Windows Communication Foundation-Komponente . So installieren Sie sie:

    1. Öffnen Sie die Visual Studio Installer-App , oder wählen Sie im Visual Studio-Menü "Tools>und Features abrufen " aus.
    2. Wählen Sie in Visual Studio Installer die Option "Ändern" neben der Version von Visual Studio aus, die Sie ändern möchten.
    3. Wählen Sie die Registerkarte "Einzelne Komponenten" und dann unter "Entwicklungsaktivitäten" die Option "Windows Communication Foundation" aus.
    4. Wählen Sie aus, umzu ändern.
  • SQL Server Express LocalDB. Wenn Sie nicht über SQL Server Express LocalDB verfügen, können Sie sie über die SQL Server-Downloadseiteinstallieren. Sie können sie auch mit der Visual Studio Installer-App als einzelne Komponente installieren.

  • SQL Server-Objekt-Explorer. Um sie zu installieren, installieren Sie die Speicher- und Verarbeitungsauslastung in der Visual Studio Installer-App .

  • Entity Framework 6-Tools. Dies wird in der Regel installiert, wenn Sie die .NET Dektop Development-Workload installieren.

Installieren und Herstellen einer Verbindung mit Northwind

Im folgenden Beispiel wird SQL Server Express LocalDB und die Northwind-Beispieldatenbank verwendet. Wenn der ADO.NET Datenanbieter für dieses Produkt Entity Framework unterstützt, sollte er auch mit anderen SQL-Datenbankprodukten verwendet werden.

Installieren Sie die Northwind-Beispieldatenbank, indem Sie die folgenden Schritte ausführen:

  1. Öffnen Sie in Visual Studio das SQL Server-Objekt-Explorer-Fenster im Menü "Ansicht ". Erweitern Sie den SQL Server-Knoten . Klicken Sie mit der rechten Maustaste auf Ihre LocalDB-Instanz, und wählen Sie "Neue Abfrage" aus.

    Ein Abfrage-Editor-Fenster wird geöffnet.

  2. Kopieren Sie das T-SQL-Skript (Northwind Transact-SQL) in die Zwischenablage.

  3. Fügen Sie das T-SQL-Skript in den Abfrage-Editor ein, und wählen Sie dann "Ausführen" aus.

    Die T-SQL-Skriptabfrage erstellt die Northwind-Datenbank und füllt sie mit Daten auf.

  4. Fügen Sie neue Verbindungen für die Northwind-Datenbank hinzu.

Konfigurieren des WPF-App-Projekts

Führen Sie die folgenden Schritte aus, um das WPF-App-Projekt zu konfigurieren:

  1. Erstellen Sie in Visual Studio ein neues C#-WPF-App (.NET Framework) Projekt.

  2. Fügen Sie das NuGet-Paket für Entity Framework 6 hinzu. Wählen Sie im Projektmappen-Explorer den Projektknoten aus. Wählen Sie im Hauptmenü Project>Manage NuGet Packagesaus.

  3. Wählen Sie im NuGet-Paket-Manager den Link "Durchsuchen" aus . Suchen Sie nach dem EntityFramework-Paket , und wählen Sie es aus. Wählen Sie " Installieren" im rechten Bereich aus, und folgen Sie den Anweisungen.

    Das Ausgabefenster zeigt den Fortschritt an und benachrichtigt Sie, wenn die Installation abgeschlossen ist.

    Screenshot des Entity Framework NuGet-Pakets.

Sie können jetzt Visual Studio verwenden, um ein Modell basierend auf der Northwind-Datenbank zu erstellen.

Erstellen des ADO.NET Entitätsdatenmodells

Führen Sie die folgenden Schritte aus, um das ADO.NET Entitätsdatenmodell zu erstellen:

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektknoten "WPF App" und wählen Sie Neues Element> aus. Wählen Sie im linken Bereich unter dem Knoten C# Daten und im mittleren Bereich ADO.NET Entitätsdatenmodellaus.

    Screenshot des Fensters

  2. Geben Sie Northwind_model für den Namen ein, und wählen Sie dann "Hinzufügen" aus.

  3. Wählen Sie im Entitätsdatenmodell-AssistentenEF Designer aus der Datenbank und dann "Weiter" aus.

    Ein Screenshot zeigt den EF Designer aus der im Assistenten für Entitätsdatenmodelle ausgewählten Datenbank.

  4. Wählen Sie in Ihre Datenverbindung Ihre LocalDB Northwind-Verbindung (z. B. (localdb)\MSSQLLocalDB) und wählen Sie dann "Weiter" aus.

  5. Wenn keine Verbindung angezeigt wird:

    1. Wählen Sie "Neue Verbindung" aus. Wenn Microsoft SQL Server nicht als Datenquelle im Dialogfeld "Verbindungseigenschaften " ausgewählt ist, wählen Sie "Ändern" aus. Wählen Sie im Dialogfeld "Datenquelle auswählen" Microsoft SQL Server und dann "OK" aus.

    2. Geben Sie im Dialogfeld "Verbindungseigenschaften " (localdb)\MSSQLLocalDB als Servernamen ein.

    3. Für Wählen Sie oder geben Sie einen Datenbanknamen ein wählen Sie Nordwind aus, und klicken Sie dann auf OK.

    4. In "Ihre Datenverbindung wählen" wählen Sie Ihre LocalDB Northwind-Verbindung aus und klicken Sie auf Weiter.

  6. Wenn Sie dazu aufgefordert werden, wählen Sie die Version von Entity Framework aus, die Sie verwenden, und wählen Sie dann "Weiter" aus.

    Screenshot der Versionsauswahl für Entity Framework.

  7. Wählen Sie auf der nächsten Seite des Assistenten aus, welche Tabellen, gespeicherten Prozeduren und andere Datenbankobjekte in das Entity Framework-Modell einbezogen werden sollen. Erweitern Sie den dbo-Knoten unter dem Tabellen-Knoten in der Strukturansicht. Wählen Sie "Kunden", "Bestelldetails" und "Bestellungen" aus. Lassen Sie die Standardwerte ausgewählt, und wählen Sie Fertig stellen.

    Screenshot der ausgewählten Datenbankobjekte des Datenmodells.

    Der Assistent generiert die C#-Klassen, die das Entity Framework-Modell darstellen und welche Visual Studio-Daten an die WPF-Benutzeroberfläche binden. Es erstellt die folgenden Dateien in Ihrem Projekt:

    • Die datei .edmx beschreibt die Beziehungen und andere Metadaten, die die Klassen objekten in der Datenbank ordnet.

    • Die .tt Dateien sind T4-Vorlagen, die den Code generieren, der auf dem Modell ausgeführt wird, und speichert Änderungen an der Datenbank.

    Diese Dateien sind im Projektmappen-Explorer unter dem Knoten Northwind_model sichtbar:

    Screenshot, der die Modelldateien von Entity Framework im Projektmappen-Explorer zeigt.

    Der Formular-Designer für die .edmx Datei wird in diesem Lernprogramm nicht verwendet, Sie können ihn jedoch verwenden, um bestimmte Eigenschaften und Beziehungen im Modell zu ändern.

Die .tt Dateien sind allgemeinen Zwecks, und Sie müssen eine davon bearbeiten, um mit der WPF-Datenbindung zu arbeiten, die ObservableCollection Objekte erfordert. Folgen Sie diesen Schritten:

  1. Erweitern Sie im Lösungs-Explorer den Knoten Northwind_model, bis Sie Northwind_model.tt finden. Doppelklicken Sie auf diese Datei, und nehmen Sie die folgenden Änderungen vor:

  2. Drücken Sie F5, um das Projekt zu erstellen und auszuführen. Wenn die Anwendung zum ersten Mal ausgeführt wird, sind die Modellklassen für den Datenquellen-Assistenten sichtbar.

Jetzt können Sie dieses Modell mit der XAML-Seite verbinden, damit Sie die Daten anzeigen, navigieren und ändern können.

Datenbindung des Modells an die XAML-Seite

Obwohl es möglich ist, Ihren eigenen Datenbindungscode zu schreiben, ist es einfacher, Visual Studio dies für Sie zu ermöglichen. Führen Sie dazu die folgenden Schritte aus:

  1. Wählen Sie im Hauptmenü Projekt>Neue Datenquelle hinzufügen aus, um den Datenquellenkonfigurations-Assistenten anzuzeigen. Da Sie an die Modellklassen binden, nicht an die Datenbank, wählen Sie "Objekt" aus. Wählen Sie Weiteraus.

    Screenshot des Datenquellenkonfigurations-Assistenten mit ausgewähltem Objekt als Datenquelle.

  2. Erweitern Sie den Knoten für Ihr Projekt, wählen Sie das Customer-Objekt und dann "Fertig stellen" aus. Die Quellen für Order-Objekte werden automatisch aus der Navigationseigenschaft Orders in Customer generiert.

    Screenshot des Kundenobjekts, das als Datenquelle ausgewählt ist.

  3. Doppelklicken Sie im Projektmappen-Explorer in Ihrem Projekt auf "MainWindow.xaml ", um den XAML-Code zu bearbeiten. Ändern Sie den Title-Wert von "MainWindow" auf einen aussagekräftigeren Namen und erhöhen Sie den Height-Wert auf 600 und den Width-Wert auf 800 (Sie können diese Werte bei Bedarf später ändern).

  4. Fügen Sie diese drei Zeilendefinitionen zum Hauptraster hinzu, eine Zeile für die Navigationsschaltflächen, eine für die Details des Kunden und eine für das Raster, in dem ihre Bestellungen angezeigt werden:

        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    

Als Nächstes zeigen Sie jede Eigenschaft in der Customers Klasse in einem eigenen textfeld an. Folgen Sie diesen Schritten:

  1. Doppelklicken Sie im Projektmappen-Explorer auf MainWindow.xaml, um sie im Designer zu öffnen.

    Die Registerkarte "Datenquellen " wird im linken Bereich von Visual Studio in der Nähe der Toolbox angezeigt.

  2. Um das Fenster "Datenquellen" zu öffnen, wählen Sie die Registerkarte "Datenquellen" aus, oder wählen Sie im Menü "Andere> anzeigen>" aus.

  3. Wählen Sie in Datenquellen " Kunden" und dann " Details " aus der Dropdownliste aus.

  4. Ziehen Sie den Knoten in die mittlere Reihe des Entwurfsbereichs. Wenn Sie es falsch platzieren, können Sie die Zeile später manuell im XAML festlegen, indem Sie Grid.Row="1" auswählen.

    Standardmäßig werden die Steuerelemente vertikal in einem Rasterelement platziert, aber Sie können sie wie im Formular anordnen. Sie können beispielsweise das Textfeld "Name " über der Adresse platzieren. In der Beispielanwendung für dieses Lernprogramm werden die Felder neu angeordnet und in zwei Spalten aufgeteilt.

    Screenshot, der die Bindung der Kundendatenquelle an einzelne Steuerelemente zeigt.

    In der XAML-Ansicht können Sie nun ein neues Grid Element in Zeile 1 (der mittleren Zeile) des übergeordneten Rasters sehen. Das übergeordnete Raster verfügt über ein DataContext Attribut, das auf ein CollectionViewSource Element verweist, das zum Windows.Resources Element gehört. Angesichts dieses Datenkontexts wird beim ersten Textfeld, das an Adresse gebunden ist, dieser Name der Address-Eigenschaft im aktuellen Customer-Objekt in CollectionViewSource zugeordnet.

    <Grid DataContext="{StaticResource customerViewSource}">
    
  5. Ziehen Sie die OrderEigenschaft des Objekts der Customers Klasse in die untere Hälfte des Formulars, sodass der Designer sie in Zeile 2 platziert.

    Wenn ein Kunde in der oberen Hälfte des Formulars sichtbar ist, möchten Sie deren Bestellungen in der unteren Hälfte anzeigen. Sie zeigen die Bestellungen in einem einzelnen Rasteransichtssteuerelement an. Damit die Master-Detail-Datenbindung erwartungsgemäß funktioniert, ist es wichtig, dass Sie eine Bindung an die Orders Eigenschaft in der Customers Klasse und nicht an den separaten Orders Knoten festlegen.

    Screenshot: Ziehen und Ablegen von Orders-Klassen als Raster

    Visual Studio generiert jetzt den gesamten Bindungscode, der die UI-Steuerelemente mit Ereignissen im Modell verbindet.

  6. Wenn Sie einige Daten anzeigen möchten, schreiben Sie Code, um das Modell aufzufüllen. Navigieren Sie zu MainWindow.xaml.cs und fügen Sie der MainWindow Klasse ein Datenelement für den Datenkontext hinzu.

    Dieses Objekt, das für Sie generiert wurde, fungiert wie ein Steuerelement, das Änderungen und Ereignisse im Modell verfolgt.

  7. Fügen Sie CollectionViewSource-Daten-Members für Kunden und Bestellungen sowie die zugehörige Konstruktor-Initialisierungslogik zum bestehenden Konstruktor MainWindow() hinzu. Der erste Teil der Klasse sollte wie folgt aussehen:

    public partial class MainWindow : Window
    {
        NorthwindEntities context = new NorthwindEntities();
        CollectionViewSource custViewSource;
        CollectionViewSource ordViewSource;
    
        public MainWindow()
        {
            InitializeComponent();
            custViewSource = ((CollectionViewSource)(FindResource("customerViewSource")));
            ordViewSource = ((CollectionViewSource)(FindResource("customerOrdersViewSource")));
            DataContext = this;
        }
    
  8. Wenn die Erweiterungsmethode nicht vorhanden ist, fügen Sie eine using-Direktive für System.Data.Entity, um die Load-Erweiterungsmethode in den Gültigkeitsbereich zu bringen.

    using System.Data.Entity;
    
  9. Scrollen Sie nach unten, und suchen Sie den Window_Loaded Ereignishandler. Beachten Sie, dass Visual Studio ein CollectionViewSource Objekt hinzugefügt hat. Dieses Objekt stellt das NorthwindEntities Objekt dar, das Sie beim Erstellen des Modells ausgewählt haben. Da Sie es bereits hinzugefügt haben, benötigen Sie es hier nicht. Ersetzen Sie den Code in Window_Loaded, sodass die Methode wie folgt aussieht:

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        // Load is an extension method on IQueryable,    
        // defined in the System.Data.Entity namespace.   
        // This method enumerates the results of the query,    
        // similar to ToList but without creating a list.   
        // When used with Linq to Entities, this method    
        // creates entity objects and adds them to the context.   
        context.Customers.Load();
    
        // After the data is loaded, call the DbSet<T>.Local property    
        // to use the DbSet<T> as a binding source.   
        custViewSource.Source = context.Customers.Local;
    }
    
  10. Drücken Sie F5.

    Sie sollten die Details für den ersten Kunden, der im CollectionViewSource abgerufen wurde, und seine Bestellungen im Datenraster sehen. Sie korrigieren die Formatierung im nächsten Abschnitt. Sie können auch eine Möglichkeit zum Anzeigen der anderen Datensätze erstellen und grundlegende Erstellungs-, Lese-, Aktualisierungs- und Löschvorgänge (CRUD) durchführen.

Anpassen des Seitendesigns und Hinzufügen von Rastern für neue Kunden und Bestellungen

Die von Visual Studio erstellte Standardanordnung eignet sich nicht ideal für Ihre Anwendung, daher stellen wir hier den endgültigen XAML-Code bereit, um sie in Ihren Code zu kopieren. Außerdem benötigen Sie einige Raster, um dem Benutzer das Hinzufügen eines neuen Kunden oder einer neuen Bestellung zu ermöglichen.

Wenn Sie einen neuen Kunden und eine neue Bestellung hinzufügen möchten, erstellen Sie einen separaten Satz von Textfeldern, die nicht an die CollectionViewSourceDaten gebunden sind. Sie steuern, welches Raster der Benutzer zu einem bestimmten Zeitpunkt sieht, indem Sie die Visible-Eigenschaft in den Handlermethoden festlegen. Schließlich fügen Sie jeder Zeile im Raster "Bestellungen" eine Schaltfläche "Löschen" hinzu, damit der Benutzer eine einzelne Bestellung löschen kann.

  1. Öffnen Sie MainWindow.xaml und fügen Sie dem Windows.Resources Element die folgenden Formatvorlagen hinzu.

    <Style x:Key="Label" TargetType="{x:Type Label}" BasedOn="{x:Null}">
       <Setter Property="HorizontalAlignment" Value="Left"/>
       <Setter Property="VerticalAlignment" Value="Center"/>
       <Setter Property="Margin" Value="3"/>
       <Setter Property="Height" Value="23"/>
    </Style>
    <Style x:Key="CustTextBox" TargetType="{x:Type TextBox}" BasedOn="{x:Null}">
       <Setter Property="HorizontalAlignment" Value="Right"/>
       <Setter Property="VerticalAlignment" Value="Center"/>
       <Setter Property="Margin" Value="3"/>
       <Setter Property="Height" Value="26"/>
       <Setter Property="Width" Value="120"/>
    </Style>
    
  2. Ersetzen Sie das gesamte äußere Raster durch dieses Markup:

    <Grid>
      <Grid.RowDefinitions>
          <RowDefinition Height="auto"/>
          <RowDefinition Height="auto"/>
          <RowDefinition Height="*"/>
      </Grid.RowDefinitions>
      <Grid x:Name="existingCustomerGrid" Grid.Row="1" HorizontalAlignment="Left" Margin="5" Visibility="Visible" VerticalAlignment="Top" Background="AntiqueWhite" DataContext="{StaticResource customerViewSource}">
          <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" MinWidth="233"/>
              <ColumnDefinition Width="Auto" MinWidth="397"/>
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
          <Label Content="Customer ID:" Grid.Row="0" Style="{StaticResource Label}"/>
          <TextBox x:Name="customerIDTextBox" Grid.Row="0" Style="{StaticResource CustTextBox}"
                   Text="{Binding CustomerID, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Company Name:" Grid.Row="1" Style="{StaticResource Label}"/>
          <TextBox x:Name="companyNameTextBox" Grid.Row="1" Style="{StaticResource CustTextBox}"
                   Text="{Binding CompanyName, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Contact Name:" Grid.Row="2" Style="{StaticResource Label}"/>
          <TextBox x:Name="contactNameTextBox" Grid.Row="2" Style="{StaticResource CustTextBox}"
                   Text="{Binding ContactName, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Contact title:" Grid.Row="3" Style="{StaticResource Label}"/>
          <TextBox x:Name="contactTitleTextBox" Grid.Row="3" Style="{StaticResource CustTextBox}"
                   Text="{Binding ContactTitle, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Address:" Grid.Row="4" Style="{StaticResource Label}"/>
          <TextBox x:Name="addressTextBox" Grid.Row="4" Style="{StaticResource CustTextBox}"
                   Text="{Binding Address, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="City:" Grid.Column="1" Grid.Row="0" Style="{StaticResource Label}"/>
          <TextBox x:Name="cityTextBox" Grid.Column="1" Grid.Row="0" Style="{StaticResource CustTextBox}"
                   Text="{Binding City, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Country:" Grid.Column="1" Grid.Row="1" Style="{StaticResource Label}"/>
          <TextBox x:Name="countryTextBox" Grid.Column="1" Grid.Row="1" Style="{StaticResource CustTextBox}"
                   Text="{Binding Country, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Fax:" Grid.Column="1" Grid.Row="2" Style="{StaticResource Label}"/>
          <TextBox x:Name="faxTextBox" Grid.Column="1" Grid.Row="2" Style="{StaticResource CustTextBox}"
                   Text="{Binding Fax, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Phone:" Grid.Column="1" Grid.Row="3" Style="{StaticResource Label}"/>
          <TextBox x:Name="phoneTextBox" Grid.Column="1" Grid.Row="3" Style="{StaticResource CustTextBox}"
                   Text="{Binding Phone, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Postal Code:" Grid.Column="1" Grid.Row="4" VerticalAlignment="Center" Style="{StaticResource Label}"/>
          <TextBox x:Name="postalCodeTextBox" Grid.Column="1" Grid.Row="4" Style="{StaticResource CustTextBox}"
                   Text="{Binding PostalCode, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Region:" Grid.Column="1" Grid.Row="5" Style="{StaticResource Label}"/>
          <TextBox x:Name="regionTextBox" Grid.Column="1" Grid.Row="5" Style="{StaticResource CustTextBox}"
                   Text="{Binding Region, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
      </Grid>
      <Grid x:Name="newCustomerGrid" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5" DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=newCustomer, UpdateSourceTrigger=Explicit}" Visibility="Collapsed" Background="CornflowerBlue">
          <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" MinWidth="233"/>
              <ColumnDefinition Width="Auto" MinWidth="397"/>
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
          <Label Content="Customer ID:" Grid.Row="0" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_customerIDTextBox" Grid.Row="0" Style="{StaticResource CustTextBox}"
                   Text="{Binding CustomerID, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Company Name:" Grid.Row="1" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_companyNameTextBox" Grid.Row="1" Style="{StaticResource CustTextBox}"
                   Text="{Binding CompanyName, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true }"/>
          <Label Content="Contact Name:" Grid.Row="2" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_contactNameTextBox" Grid.Row="2" Style="{StaticResource CustTextBox}"
                   Text="{Binding ContactName, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Contact title:" Grid.Row="3" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_contactTitleTextBox" Grid.Row="3" Style="{StaticResource CustTextBox}"
                   Text="{Binding ContactTitle, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Address:" Grid.Row="4" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_addressTextBox" Grid.Row="4" Style="{StaticResource CustTextBox}"
                   Text="{Binding Address, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="City:" Grid.Column="1" Grid.Row="0" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_cityTextBox" Grid.Column="1" Grid.Row="0" Style="{StaticResource CustTextBox}"
                   Text="{Binding City, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Country:" Grid.Column="1" Grid.Row="1" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_countryTextBox" Grid.Column="1" Grid.Row="1" Style="{StaticResource CustTextBox}"
                   Text="{Binding Country, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Fax:" Grid.Column="1" Grid.Row="2" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_faxTextBox" Grid.Column="1" Grid.Row="2" Style="{StaticResource CustTextBox}"
                   Text="{Binding Fax, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Phone:" Grid.Column="1" Grid.Row="3" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_phoneTextBox" Grid.Column="1" Grid.Row="3" Style="{StaticResource CustTextBox}"
                   Text="{Binding Phone, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Postal Code:" Grid.Column="1" Grid.Row="4" VerticalAlignment="Center" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_postalCodeTextBox" Grid.Column="1" Grid.Row="4" Style="{StaticResource CustTextBox}"
                   Text="{Binding PostalCode, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Region:" Grid.Column="1" Grid.Row="5" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_regionTextBox" Grid.Column="1" Grid.Row="5" Style="{StaticResource CustTextBox}"
                   Text="{Binding Region, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
      </Grid>
      <Grid x:Name="newOrderGrid" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5" DataContext="{Binding Path=newOrder, Mode=TwoWay}" Visibility="Collapsed" Background="LightGreen">
          <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" MinWidth="233"/>
              <ColumnDefinition Width="Auto" MinWidth="397"/>
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
          </Grid.RowDefinitions>
          <Label Content="New Order Form" FontWeight="Bold"/>
          <Label Content="Employee ID:"  Grid.Row="1" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_employeeIDTextBox" Grid.Row="1" Style="{StaticResource CustTextBox}"
                   Text="{Binding EmployeeID, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Order Date:"  Grid.Row="2" Style="{StaticResource Label}"/>
          <DatePicker x:Name="add_orderDatePicker" Grid.Row="2"  HorizontalAlignment="Right" Width="120"
                  SelectedDate="{Binding OrderDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=PropertyChanged}"/>
          <Label Content="Required Date:" Grid.Row="3" Style="{StaticResource Label}"/>
          <DatePicker x:Name="add_requiredDatePicker" Grid.Row="3" HorizontalAlignment="Right" Width="120"
                   SelectedDate="{Binding RequiredDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=PropertyChanged}"/>
          <Label Content="Shipped Date:"  Grid.Row="4"  Style="{StaticResource Label}"/>
          <DatePicker x:Name="add_shippedDatePicker"  Grid.Row="4"  HorizontalAlignment="Right" Width="120"
                  SelectedDate="{Binding ShippedDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=PropertyChanged}"/>
          <Label Content="Ship Via:"  Grid.Row="5" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_ShipViaTextBox"  Grid.Row="5" Style="{StaticResource CustTextBox}"
                   Text="{Binding ShipVia, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
          <Label Content="Freight"  Grid.Row="6" Style="{StaticResource Label}"/>
          <TextBox x:Name="add_freightTextBox" Grid.Row="6" Style="{StaticResource CustTextBox}"
                   Text="{Binding Freight, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}"/>
      </Grid>
      <DataGrid x:Name="ordersDataGrid" SelectionUnit="Cell" SelectionMode="Single" AutoGenerateColumns="False" CanUserAddRows="false" IsEnabled="True" EnableRowVirtualization="True" Width="auto" ItemsSource="{Binding Source={StaticResource customerOrdersViewSource}}" Margin="10,10,10,10" Grid.Row="2" RowDetailsVisibilityMode="VisibleWhenSelected">
          <DataGrid.Columns>
              <DataGridTemplateColumn>
                  <DataGridTemplateColumn.CellTemplate>
                      <DataTemplate>
                          <Button Content="Delete" Command="{StaticResource DeleteOrderCommand}" CommandParameter="{Binding}"/>
                      </DataTemplate>
                  </DataGridTemplateColumn.CellTemplate>
              </DataGridTemplateColumn>
              <DataGridTextColumn x:Name="customerIDColumn" Binding="{Binding CustomerID}" Header="Customer ID" Width="SizeToHeader"/>
              <DataGridTextColumn x:Name="employeeIDColumn" Binding="{Binding EmployeeID}" Header="Employee ID" Width="SizeToHeader"/>
              <DataGridTextColumn x:Name="freightColumn" Binding="{Binding Freight}" Header="Freight" Width="SizeToHeader"/>
              <DataGridTemplateColumn x:Name="orderDateColumn" Header="Order Date" Width="SizeToHeader">
                  <DataGridTemplateColumn.CellTemplate>
                      <DataTemplate>
                          <DatePicker SelectedDate="{Binding OrderDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=PropertyChanged}"/>
                      </DataTemplate>
                  </DataGridTemplateColumn.CellTemplate>
              </DataGridTemplateColumn>
              <DataGridTextColumn x:Name="orderIDColumn" Binding="{Binding OrderID}" Header="Order ID" Width="SizeToHeader"/>
              <DataGridTemplateColumn x:Name="requiredDateColumn" Header="Required Date" Width="SizeToHeader">
                  <DataGridTemplateColumn.CellTemplate>
                      <DataTemplate>
                          <DatePicker SelectedDate="{Binding RequiredDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=PropertyChanged}"/>
                      </DataTemplate>
                  </DataGridTemplateColumn.CellTemplate>
              </DataGridTemplateColumn>
              <DataGridTextColumn x:Name="shipAddressColumn" Binding="{Binding ShipAddress}" Header="Ship Address" Width="SizeToHeader"/>
              <DataGridTextColumn x:Name="shipCityColumn" Binding="{Binding ShipCity}" Header="Ship City" Width="SizeToHeader"/>
              <DataGridTextColumn x:Name="shipCountryColumn" Binding="{Binding ShipCountry}" Header="Ship Country" Width="SizeToHeader"/>
              <DataGridTextColumn x:Name="shipNameColumn" Binding="{Binding ShipName}" Header="Ship Name" Width="SizeToHeader"/>
              <DataGridTemplateColumn x:Name="shippedDateColumn" Header="Shipped Date" Width="SizeToHeader">
                  <DataGridTemplateColumn.CellTemplate>
                      <DataTemplate>
                          <DatePicker SelectedDate="{Binding ShippedDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, UpdateSourceTrigger=PropertyChanged}"/>
                      </DataTemplate>
                  </DataGridTemplateColumn.CellTemplate>
              </DataGridTemplateColumn>
              <DataGridTextColumn x:Name="shipPostalCodeColumn" Binding="{Binding ShipPostalCode}" Header="Ship Postal Code" Width="SizeToHeader"/>
              <DataGridTextColumn x:Name="shipRegionColumn" Binding="{Binding ShipRegion}" Header="Ship Region" Width="SizeToHeader"/>
              <DataGridTextColumn x:Name="shipViaColumn" Binding="{Binding ShipVia}" Header="Ship Via" Width="SizeToHeader"/>
          </DataGrid.Columns>
       </DataGrid>
    </Grid>
    

Hinzufügen von Schaltflächen zum Navigieren, Hinzufügen, Aktualisieren und Löschen

In einer Windows Forms-Anwendung erhalten Sie ein BindingNavigator Objekt mit Schaltflächen zum Navigieren durch Zeilen in einer Datenbank und ausführen grundlegender CRUD-Vorgänge. Obwohl WPF kein Element bereitstellt BindingNavigator, ist es einfach, eine zu erstellen, indem Schaltflächen innerhalb einer horizontalen StackPanelErstellt werden, und die Schaltflächen den Befehlen zugeordnet werden, die an Methoden in der CodeBehind-Datei gebunden sind.

Es gibt vier Teile der Befehlslogik:

  • Befehle
  • Bindungen
  • Knöpfe
  • Befehlshandler im Code-behind

Hinzufügen von Befehlen, Bindungen und Schaltflächen in XAML

  1. Fügen Sie in der MainWindow.xaml Datei die Befehle im Windows.Resources Element wie folgt hinzu:

    <RoutedUICommand x:Key="FirstCommand" Text="First"/>
    <RoutedUICommand x:Key="LastCommand" Text="Last"/>
    <RoutedUICommand x:Key="NextCommand" Text="Next"/>
    <RoutedUICommand x:Key="PreviousCommand" Text="Previous"/>
    <RoutedUICommand x:Key="DeleteCustomerCommand" Text="Delete Customer"/>
    <RoutedUICommand x:Key="DeleteOrderCommand" Text="Delete Order"/>
    <RoutedUICommand x:Key="UpdateCommand" Text="Update"/>
    <RoutedUICommand x:Key="AddCommand" Text="Add"/>
    <RoutedUICommand x:Key="CancelCommand" Text="Cancel"/>
    
  2. Ein CommandBinding ordnet ein RoutedUICommand-Ereignis einer Methode im CodeBehind zu. Fügen Sie dieses CommandBindings Element nach dem abschließenden Windows.Resources-Tag wie folgt ein:

    <Window.CommandBindings>
        <CommandBinding Command="{StaticResource FirstCommand}" Executed="FirstCommandHandler"/>
        <CommandBinding Command="{StaticResource LastCommand}" Executed="LastCommandHandler"/>
        <CommandBinding Command="{StaticResource NextCommand}" Executed="NextCommandHandler"/>
        <CommandBinding Command="{StaticResource PreviousCommand}" Executed="PreviousCommandHandler"/>
        <CommandBinding Command="{StaticResource DeleteCustomerCommand}" Executed="DeleteCustomerCommandHandler"/>
        <CommandBinding Command="{StaticResource DeleteOrderCommand}" Executed="DeleteOrderCommandHandler"/>
        <CommandBinding Command="{StaticResource UpdateCommand}" Executed="UpdateCommandHandler"/>
        <CommandBinding Command="{StaticResource AddCommand}" Executed="AddCommandHandler"/>
        <CommandBinding Command="{StaticResource CancelCommand}" Executed="CancelCommandHandler"/>
    </Window.CommandBindings>
    
  3. Fügen Sie die StackPanel Schaltflächen "Navigation", "Hinzufügen", "Löschen" und "Aktualisieren" hinzu. Fügen Sie diesen Stil zu Windows.Resources hinzu.

    <Style x:Key="NavButton" TargetType="{x:Type Button}" BasedOn="{x:Null}">
        <Setter Property="FontSize" Value="24"/>
        <Setter Property="FontFamily" Value="Segoe UI Symbol"/>
        <Setter Property="Margin" Value="2,2,2,0"/>
        <Setter Property="Width" Value="40"/>
        <Setter Property="Height" Value="auto"/>
    </Style>
    
  4. Fügen Sie diesen Code direkt nach dem RowDefinitions für das äußere Grid Element nahe dem oberen Rand der XAML-Seite ein.

     <StackPanel Orientation="Horizontal" Margin="2,2,2,0" Height="36" VerticalAlignment="Top" Background="Gainsboro" DataContext="{StaticResource customerViewSource}" d:LayoutOverrides="LeftMargin, RightMargin, TopMargin, BottomMargin">
         <Button Name="btnFirst" Content="|◄" Command="{StaticResource FirstCommand}" Style="{StaticResource NavButton}"/>
         <Button Name="btnPrev" Content="◄" Command="{StaticResource PreviousCommand}" Style="{StaticResource NavButton}"/>
         <Button Name="btnNext" Content="►" Command="{StaticResource NextCommand}" Style="{StaticResource NavButton}"/>
         <Button Name="btnLast" Content="►|" Command="{StaticResource LastCommand}" Style="{StaticResource NavButton}"/>
         <Button Name="btnDelete" Content="Delete Customer" Command="{StaticResource DeleteCustomerCommand}" FontSize="11" Width="120" Style="{StaticResource NavButton}"/>
         <Button Name="btnAdd" Content="New Customer" Command="{StaticResource AddCommand}" FontSize="11" Width="80" Style="{StaticResource NavButton}"/>
         <Button Content="New Order" Name="btnNewOrder" FontSize="11" Width="80" Style="{StaticResource NavButton}" Click="NewOrder_click"/>
         <Button Name="btnUpdate" Content="Commit" Command="{StaticResource UpdateCommand}" FontSize="11" Width="80" Style="{StaticResource NavButton}"/>
         <Button Content="Cancel" Name="btnCancel" Command="{StaticResource CancelCommand}" FontSize="11" Width="80" Style="{StaticResource NavButton}"/>
     </StackPanel>
    

Hinzufügen von Befehlshandlern zur MainWindow-Klasse

Der Code-Behind in MainWindow.xaml.cs ist bis auf die Methoden add und delete minimal:

  1. Um zu navigieren, rufen Sie Methoden für die View-Eigenschaft von CollectionViewSource auf.

  2. Um eine Bestellung kaskadenartig zu löschen, verwenden Sie das DeleteOrderCommandHandler wie im Code-Beispiel gezeigt. Allerdings müssen Sie zuerst das zugehörige Order_Details der Bestellung löschen.

  3. Verwenden Sie die UpdateCommandHandler Möglichkeit, der Sammlung einen Kunden oder eine Bestellung hinzuzufügen oder einen vorhandenen Kunden oder eine vorhandene Bestellung mit den Änderungen zu aktualisieren, die der Benutzer in den Textfeldern vorgibt.

  4. Fügen Sie diese Handlermethoden zur Klasse MainWindow in MainWindow.xaml.cs hinzu. Wenn Ihr CollectionViewSource für die Tabelle Customers einen anderen Namen hat, müssen Sie den Namen in jeder der Methoden anpassen:

    private void LastCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        custViewSource.View.MoveCurrentToLast();
    }
    
    private void PreviousCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        custViewSource.View.MoveCurrentToPrevious();
    }
    
    private void NextCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        custViewSource.View.MoveCurrentToNext();
    }
    
    private void FirstCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        custViewSource.View.MoveCurrentToFirst();
    }
    
    private void DeleteCustomerCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        // If existing window is visible, delete the customer and all their orders.  
        // In a real application, you should add warnings and allow the user to cancel the operation.  
        var cur = custViewSource.View.CurrentItem as Customer;
    
        var cust = (from c in context.Customers
                    where c.CustomerID == cur.CustomerID
                    select c).FirstOrDefault();
    
        if (cust != null)
        {
            foreach (var ord in cust.Orders.ToList())
            {
                Delete_Order(ord);
            }
            context.Customers.Remove(cust);
        }
        context.SaveChanges();
        custViewSource.View.Refresh();
    }
    
    // Commit changes from the new customer form, the new order form,  
    // or edits made to the existing customer form.  
    private void UpdateCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        if (newCustomerGrid.IsVisible)
        {
            // Create a new object because the old one  
            // is being tracked by EF now.  
            Customer newCustomer = new Customer
            {
                Address = add_addressTextBox.Text,
                City = add_cityTextBox.Text,
                CompanyName = add_companyNameTextBox.Text,
                ContactName = add_contactNameTextBox.Text,
                ContactTitle = add_contactTitleTextBox.Text,
                Country = add_countryTextBox.Text,
                CustomerID = add_customerIDTextBox.Text,
                Fax = add_faxTextBox.Text,
                Phone = add_phoneTextBox.Text,
                PostalCode = add_postalCodeTextBox.Text,
                Region = add_regionTextBox.Text
            };
    
            // Perform very basic validation  
            if (newCustomer.CustomerID.Length == 5)
            {
                // Insert the new customer at correct position:  
                int len = context.Customers.Local.Count();
                int pos = len;
                for (int i = 0; i < len; ++i)
                {
                    if (String.CompareOrdinal(newCustomer.CustomerID, context.Customers.Local[i].CustomerID) < 0)
                    {
                        pos = i;
                        break;
                    }
                }
                context.Customers.Local.Insert(pos, newCustomer);
                custViewSource.View.Refresh();
                custViewSource.View.MoveCurrentTo(newCustomer);
            }
            else
            {
                MessageBox.Show("CustomerID must have 5 characters.");
            }
    
            newCustomerGrid.Visibility = Visibility.Collapsed;
            existingCustomerGrid.Visibility = Visibility.Visible;
        }
        else if (newOrderGrid.IsVisible)
        {
            // Order ID is auto-generated so we don't set it here.  
            // For CustomerID, address, etc we use the values from current customer.  
            // User can modify these in the datagrid after the order is entered.  
    
            Customer currentCustomer = (Customer)custViewSource.View.CurrentItem;
    
            Order newOrder = new Order()
            {
                OrderDate = add_orderDatePicker.SelectedDate,
                RequiredDate = add_requiredDatePicker.SelectedDate,
                ShippedDate = add_shippedDatePicker.SelectedDate,
                CustomerID = currentCustomer.CustomerID,
                ShipAddress = currentCustomer.Address,
                ShipCity = currentCustomer.City,
                ShipCountry = currentCustomer.Country,
                ShipName = currentCustomer.CompanyName,
                ShipPostalCode = currentCustomer.PostalCode,
                ShipRegion = currentCustomer.Region
            };
    
            try
            {
                newOrder.EmployeeID = Int32.Parse(add_employeeIDTextBox.Text);
            }
            catch
            {
                MessageBox.Show("EmployeeID must be a valid integer value.");
                return;
            }
    
            try
            {
                // Exercise for the reader if you are using Northwind:  
                // Add the Northwind Shippers table to the model.
                
                // Acceptable ShipperID values are 1, 2, or 3.  
                if (add_ShipViaTextBox.Text == "1" || add_ShipViaTextBox.Text == "2"
                    || add_ShipViaTextBox.Text == "3")
                {
                    newOrder.ShipVia = Convert.ToInt32(add_ShipViaTextBox.Text);
                }
                else
                {
                    MessageBox.Show("Shipper ID must be 1, 2, or 3 in Northwind.");
                    return;
                }
            }
            catch
            {
                MessageBox.Show("Ship Via must be convertible to int");
                return;
            }
    
            try
            {
                newOrder.Freight = Convert.ToDecimal(add_freightTextBox.Text);
            }
            catch
            {
                MessageBox.Show("Freight must be convertible to decimal.");
                return;
            }
    
            // Add the order into the EF model  
            context.Orders.Add(newOrder);
            ordViewSource.View.Refresh();
        }
    
        // Save the changes, either for a new customer, a new order  
        // or an edit to an existing customer or order.
        context.SaveChanges();
    }
    
    // Sets up the form so that user can enter data. Data is later  
    // saved when user clicks Commit.  
    private void AddCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        existingCustomerGrid.Visibility = Visibility.Collapsed;
        newOrderGrid.Visibility = Visibility.Collapsed;
        newCustomerGrid.Visibility = Visibility.Visible;
    
        // Clear all the text boxes before adding a new customer.  
        foreach (var child in newCustomerGrid.Children)
        {
            var tb = child as TextBox;
            if (tb != null)
            {
                tb.Text = "";
            }
        }
    }
    
    private void NewOrder_click(object sender, RoutedEventArgs e)
    {
        var cust = custViewSource.View.CurrentItem as Customer;
        if (cust == null)
        {
            MessageBox.Show("No customer selected.");
            return;
        }
    
        existingCustomerGrid.Visibility = Visibility.Collapsed;
        newCustomerGrid.Visibility = Visibility.Collapsed;
        newOrderGrid.UpdateLayout();
        newOrderGrid.Visibility = Visibility.Visible;
    }
    
    // Cancels any input into the new customer form  
    private void CancelCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        add_addressTextBox.Text = "";
        add_cityTextBox.Text = "";
        add_companyNameTextBox.Text = "";
        add_contactNameTextBox.Text = "";
        add_contactTitleTextBox.Text = "";
        add_countryTextBox.Text = "";
        add_customerIDTextBox.Text = "";
        add_faxTextBox.Text = "";
        add_phoneTextBox.Text = "";
        add_postalCodeTextBox.Text = "";
        add_regionTextBox.Text = "";
    
        existingCustomerGrid.Visibility = Visibility.Visible;
        newCustomerGrid.Visibility = Visibility.Collapsed;
        newOrderGrid.Visibility = Visibility.Collapsed;
    }
    
    private void Delete_Order(Order order)
    {
        // Find the order in the EF model.  
        var ord = (from o in context.Orders.Local
                   where o.OrderID == order.OrderID
                   select o).FirstOrDefault();
    
        // Delete all the order_details that have  
        // this Order as a foreign key  
        foreach (var detail in ord.Order_Details.ToList())
        {
            context.Order_Details.Remove(detail);
        }
    
        // Now it's safe to delete the order.  
        context.Orders.Remove(ord);
        context.SaveChanges();
    
        // Update the data grid.  
        ordViewSource.View.Refresh();
    }
    
    private void DeleteOrderCommandHandler(object sender, ExecutedRoutedEventArgs e)
    {
        // Get the Order in the row in which the Delete button was clicked.  
        Order obj = e.Parameter as Order;
        Delete_Order(obj);
    }
    

Ausführen der WPF-Anwendung

  1. Um mit dem Debuggen zu beginnen, drücken Sie F5. Stellen Sie sicher, dass Kunden- und Bestelldaten im Raster aufgefüllt werden, und die Navigationsschaltflächen funktionieren wie erwartet.

  2. Wählen Sie "Commit" aus, um einen neuen Kunden oder eine Bestellung zum Modell hinzuzufügen, nachdem Sie die Daten eingegeben haben.

  3. Wählen Sie "Abbrechen" aus, um ein neues Kunden- oder neues Bestellformular zu löschen, ohne die Daten zu speichern.

  4. Wenn Sie vorhandene Kunden und Bestellungen direkt bearbeiten möchten, verwenden Sie die Textfelder, die diese Änderungen automatisch in das Modell schreiben.