使用 WPF 和 Entity Framework 6 建立簡單的資料應用程式Create a simple data application with WPF and Entity Framework 6

本逐步解說示範如何在 Visual Studio 中建立基本 「 資料表單 」 應用程式。This walkthrough shows how to create a basic "forms over data" application in Visual Studio. SQL Server LocalDB,Northwind 資料庫中,Entity Framework 6,與 Windows Presentation Foundation,則會使用應用程式。The app uses SQL Server LocalDB, the Northwind database, Entity Framework 6, and Windows Presentation Foundation. 它示範如何執行基本的資料繫結,主版詳細資料檢視,而且也有自訂繫結瀏覽器,並用於按鈕移到下一個移到上一個移動開始移到結尾更新刪除It shows how to do basic databinding with a master-detail view, and it also has a custom Binding Navigator with buttons for Move Next, Move Previous, Move to beginning, Move to end, Update and Delete.

本文著重於在 Visual Studio 中,使用資料的工具,並不會嘗試說明中任意深度的基礎技術。This article focuses on using data tools in Visual Studio, and does not attempt to explain the underlying technologies in any depth. 這裡假設您有基本的熟悉 XAML、 Entity Framework 和 SQL。It assumes that you have a basic familiarity with XAML, Entity Framework, and SQL. 此範例中也不會示範 Model View ViewModel (MVVM) 架構,也就是標準 WPF 應用程式。This example also does not demonstrate Model-View-ViewModel (MVVM) architecture, which is standard for WPF applications. 不過,您也可以將此程式碼複製到自己的 MVVM 應用程式,需稍微修改一下。However, you can copy this code into your own MVVM application with few modifications.

安裝並連接到 NorthwindInstall and connect to Northwind

此範例會使用 SQL Server Express LocalDB 和 Northwind 範例資料庫。This example uses SQL Server Express LocalDB and the Northwind sample database. 如果該產品的 ADO.NET 資料提供者支援 Entity Framework,它就應該也使用其他的 SQL 資料庫產品。If the ADO.NET data provider for that product supports Entity Framework, it should work with other SQL database products just as well.

  1. 如果您沒有 SQL Server Express LocalDB,請將它安裝從SQL Server Express 下載頁面,或透過Visual Studio 安裝程式If you don't have SQL Server Express LocalDB, install it either from the SQL Server Express download page, or through the Visual Studio Installer. Visual Studio 安裝程式,您可以安裝 SQL Server Express LocalDB 做為一部分 .NET 桌面開發工作負載或個別的元件。In the Visual Studio Installer, you can install SQL Server Express LocalDB as part of the .NET desktop development workload or as an individual component.

  2. 安裝 Northwind 範例資料庫執行下列步驟:Install the Northwind sample database by following these steps:

    1. 在 Visual Studio 中開啟SQL Server 物件總管視窗。In Visual Studio, open the SQL Server Object Explorer window. (SQL Server 物件總管安裝的一部分資料儲存和處理中的工作負載Visual Studio 安裝程式。)依序展開SQL Server節點。(SQL Server Object Explorer is installed as part of the Data storage and processing workload in the Visual Studio Installer.) Expand the SQL Server node. 以滑鼠右鍵按一下您的 LocalDB 執行個體,然後選取新的查詢Right-click on your LocalDB instance and select New Query.

      查詢編輯器視窗隨即開啟。A query editor window opens.

    2. 複製Northwind 的 TRANSACT-SQL 指令碼到剪貼簿。Copy the Northwind Transact-SQL script to your clipboard. 這個 T-SQL 指令碼會從頭建立 Northwind 資料庫,並填入資料。This T-SQL script creates the Northwind database from scratch and populates it with data.

    3. 將 T-SQL 指令碼貼到查詢編輯器,然後選擇Execute 按鈕。Paste the T-SQL script into the query editor, and then choose the Execute button.

      短時間之後,查詢完成執行,並建立 Northwind 資料庫。After a short time, the query finishes running and the Northwind database is created.

  3. 加入新連接northwind。Add new connections for Northwind.

設定專案Configure the project

  1. 在 Visual Studio 中建立新的C# WPF 應用程式專案。In Visual Studio, create a new C# WPF App project.

  2. 新增 NuGet 套件的 Entity Framework 6。Add the NuGet package for Entity Framework 6. 在 [方案總管] 中,選取 [專案] 節點。In Solution Explorer, select the project node. 在主功能表中,選擇專案 > 管理 NuGet 套件In the main menu, choose Project > Manage NuGet Packages.

    管理 NuGet 套件 功能表項目

  3. NuGet 套件管理員,按一下瀏覽連結。In the NuGet Package Manager, click on the Browse link. Entity Framework 可能是最上層的套件清單中。Entity Framework is probably the top package in the list. 按一下 安裝右窗格中,並遵循提示。Click Install in the right pane and follow the prompts. [輸出] 視窗會告訴您完成安裝。The Output window tells you when the install is finished.

    Entity Framework NuGet 套件

  4. 現在您可以使用 Visual Studio 來建立模型,根據 Northwind 資料庫。Now you can use Visual Studio to create a model based on the Northwind database.

建立模型Create the model

  1. 中的專案節點上按一下滑鼠右鍵方案總管,然後選擇新增 > 新項目Right-click on the project node in Solution Explorer and choose Add > New Item. 在左窗格中,C#] 節點底下,選擇資料,然後在中間窗格中,選擇 [ ADO.NET 實體資料模型In the left pane, under the C# node, choose Data and in the middle pane, choose ADO.NET Entity Data Model.

    Entity Framework 模型新項目

  2. 呼叫模型Northwind_model,然後選擇 確定Call the model Northwind_model and choose OK. [實體資料模型精靈] 隨即開啟。The Entity Data Model Wizard opens. 選擇資料庫的 EF Designer ,然後按一下下一步Choose EF Designer from database and then click Next.

    從資料庫的 EF 模型

  3. 在下一個畫面中,選擇您的 LocalDB Northwind 連接,然後按一下 [下一步]In the next screen, choose your LocalDB Northwind connection and click Next.

  4. 在精靈的下一個頁面中,選擇哪些資料表、 預存程序,以及要包含在 Entity Framework 模型中其他資料庫物件。In the next page of the wizard, choose which tables, stored procedures, and other database objects to include in the Entity Framework model. 展開樹狀檢視中的 [dbo] 節點,然後選擇客戶訂單,並Order DetailsExpand the dbo node in the tree view and choose Customers, Orders, and Order Details. 保留選取預設值,然後按一下完成Leave the defaults checked and click Finish.

    選擇模型的資料庫物件

  5. 精靈會產生代表 Entity Framework 模型的 C# 類別。The wizard generates the C# classes that represent the Entity Framework model. 類別是純舊 C# 類別,而且是我們繫結至 WPF 使用者介面。The classes are plain old C# classes and they are what we databind to the WPF user interface. .Edmx檔案會描述關聯性和其他中繼資料與資料庫中的物件產生關聯的類別。The .edmx file describes the relationships and other metadata that associates the classes with objects in the database. .Tt檔案會產生運作模型,並將變更儲存到資料庫的程式碼的 T4 範本。The .tt files are T4 templates that generate the code that operates on the model and save changes to the database. 您可以看到所有這些檔案中的方案總管 中Northwind_model 節點下:You can see all these files in Solution Explorer under the Northwind_model node:

    方案總管 EF 模型檔案

    設計工具介面 .edmx檔案可讓您修改一些屬性和模型中的關聯性。The designer surface for the .edmx file enables you to modify some properties and relationships in the model. 我們不會在本逐步解說使用設計工具。We are not going to use the designer in this walkthrough.

  6. .Tt檔案是一般用途,您需要調整其中一個,才能使用 WPF 資料繫結,需要 ObservableCollections。The .tt files are general purpose and you need to tweak one of them to work with WPF databinding, which requires ObservableCollections. 方案總管,展開 Northwind_model 節點,直到您找到Northwind_model.ttIn Solution Explorer, expand the Northwind_model node until you find Northwind_model.tt. (請確定您不是處於 。Context.tt檔案,這是正下方 .edmx檔案。)(Make sure you are not in the .Context.tt file, which is directly below the .edmx file.)

  7. 按下Ctrl+Shift+B來建置專案。Press Ctrl+Shift+B to build the project. 當組建完成時,模型類別會顯示資料來源精靈。When the build finishes, the model classes are visible to the data sources wizard.

現在您已準備好將連結至 XAML 頁面的這個模型,讓您可以檢視、 巡覽及修改資料。Now you are ready to hook up this model to the XAML page so that you can view, navigate, and modify the data.

資料繫結至 XAML 頁面模型Databind the model to the XAML page

可以撰寫自己的資料繫結程式碼,但很容易讓您執行的 Visual Studio。It is possible to write your own databinding code, but it is much easier to let Visual Studio do it for you.

  1. 從主功能表中,選擇專案 > 新增新的資料來源以顯示資料來源組態精靈From the main menu, choose Project > Add new data source to bring up the Data Source Configuration Wizard. 選擇物件因為您要繫結模型類別,不是針對資料庫:Choose Object because you are binding to the model classes, not to the database:

    與物件來源的資料來源組態精靈

  2. 選取 客戶Select Customer. (如訂單的來源會自動產生從客戶的訂單導覽屬性。)(Sources for Orders are automatically generated from the Orders navigation property in Customer.)

    將實體類別加入做為資料來源

  3. 按一下 [ 完成]。Click Finish.

  4. 瀏覽至MainWindow.xaml程式碼檢視中。Navigate to MainWindow.xaml in Code View. 我們將保留 XAML 簡單基於此範例的目的。We're keeping the XAML simple for the purposes of this example. MainWindow 的標題變更為更具描述性,並增加其高度和寬度為 600 x 800 現在。Change the title of MainWindow to something more descriptive, and increase its Height and Width to 600 x 800 for now. 您之後隨時可以變更它。You can always change it later. 現在請將下列三個資料列定義新增至在主要方格中,瀏覽按鈕,一個用於客戶的詳細資訊,,一個用於顯示其訂單的方格中的一個資料列:Now add these three row definitions to the main grid, one row for the navigation buttons, one for the customer's details, and one for the grid that shows their orders:

    <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    
  5. 現在,請開啟MainWindow.xaml ,讓您在設計工具中檢視它。Now open MainWindow.xaml so that you're viewing it in the designer. 這會導致資料來源視窗旁邊會出現在 Visual Studio 視窗邊界選項工具箱This causes the Data Sources window to appear as an option in the Visual Studio window margin next to the Toolbox. 若要開啟視窗,否則按 索引標籤上按一下Shift+Alt+D ,或選擇檢視 > 其他 Windows > Zdroje datClick on the tab to open the window, or else press Shift+Alt+D or choose View > Other Windows > Data Sources. 我們將客戶類別,在它自己的個別文字 方塊中顯示每個屬性。We are going to display each property in the Customers class in its own individual text box. 首先,請按一下中的箭號客戶下拉式方塊,然後選擇詳細資料First, click on the arrow in the Customers combo box and choose Details. 讓設計工具可讓您知道您想要在中間的資料列,然後拖曳到設計介面的中間部分節點。Then, drag the node onto the middle part of the design surface so that the designer knows you want it to go in the middle row. 如果您弄丟它,您可以在稍後以手動方式在 XAML 中指定的資料列。If you misplace it, you can specify the row manually later in the XAML. 根據預設,控制項置於垂直格線項目中,但到目前為止,您可以加以排列表單上。By default, the controls are placed vertically in a grid element, but at this point, you can arrange them however you like on the form. 比方說,可能會合理放名稱文字方塊中,在最上層,上述的位址。For example, it might make sense to put the Name text box on top, above the address. 這篇文章的範例應用程式重新排列欄位,而會將它們重新排列成兩個資料行。The sample application for this article reorders the fields and rearranges them into two columns.

    客戶的資料來源繫結至個別的控制項

    在程式碼檢視中,您現在可以看到新Grid項目中資料列 1 (中間的資料列) 的父格線。In the code view, you can now see a new Grid element in row 1 (the middle row) of the parent Grid. 方格具有父代DataContext屬性,會參考至已加入至 CollectionViewSourceWindows.Resources項目。The parent Grid has a DataContext attribute that refers to a CollectionViewSource that's been added to the Windows.Resources element. 指定該資料內容,當第一個文字方塊繫結至地址,該名稱會對應至Address在目前的屬性CustomerCollectionViewSource 中的物件。Given that data context, when the first text box binds to Address, that name is mapped to the Address property in the current Customer object in the CollectionViewSource.

    <Grid DataContext="{StaticResource customerViewSource}">
    
  6. 客戶在上半部的視窗顯示時,您會想要另外一半查看其在底部的訂單。When a customer is visible in the top half of the window, you want to see their orders in the bottom half. 您在單一格線檢視控制項中顯示的訂單。You show the orders in a single grid view control. 針對主版詳細資料繫結至如預期般運作,很重要,您將繫結至客戶類別,不會以個別的 [訂單] 節點中的 Orders 屬性。For master-detail databinding to work as expected, it is important that you bind to the Orders property in the Customers class, not to the separate Orders node. 將客戶類別的 Orders 屬性拖曳到表單的下半部,讓設計工具會將它置於第 2 列:Drag the Orders property of the Customers class to the lower half of the form, so that the designer puts it in row 2:

    以方格顯示將訂單類別

  7. Visual Studio 已產生的所有繫結程式碼的 UI 控制項連接至模型中的事件。Visual Studio has generated all the binding code that connects the UI controls to events in the model. 您只需要執行動作,才能看到某些資料,是撰寫一些程式碼來擴展模型。All you need to do, in order to see some data, is to write some code to populate the model. 首先,瀏覽至MainWindow.xaml.cs並將資料成員新增至 MainWindow 類別的資料內容。First, navigate to MainWindow.xaml.cs and add a data member to the MainWindow class for the data context. 為您產生之後,這個物件是類似的控制項,會追蹤變更以及在模型中的事件。This object, which has been generated for you, acts something like a control that tracks changes and events in the model. 您也將新增建構函式的初始化邏輯。You'll also add the constructor initialization logic. 類別的頂端應該看起來像這樣:The top of the class should look like this:

    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;
        }
    

    新增usingLoad 擴充方法帶入範圍內的 System.Data.Entity 指示詞:Add a using directive for System.Data.Entity to bring the Load extension method into scope:

    using System.Data.Entity;
    

    現在,向下捲動並尋找Window_Loaded事件處理常式。Now, scroll down and find the Window_Loaded event handler. 請注意,Visual Studio 新增 CollectionViewSource 物件。Notice that Visual Studio has added a CollectionViewSource object. 這表示您在建立模型時所選取的 NorthwindEntities 物件。This represents the NorthwindEntities object that you selected when you created the model. 讓我們將程式碼加入Window_Loaded使整個方法現在看起來像這樣:Let's add code to Window_Loaded so that the entire method now looks like this:

    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;
    }
    
  8. 請按 F5Press F5. 您應該會看到針對至 CollectionViewSource 已擷取的第一個客戶詳細資料。You should see the details for the first customer that was retrieved into the CollectionViewSource. 您也應該會看到他們在資料格中的訂單。You should also see their orders in the data grid. 格式不太好了,現在讓我們來修正,就行了。The formatting isn't great, so let's fix that up. 您也可以建立檢視的其他記錄和執行基本 CRUD 作業的方式。You can also create a way to view the other records and do basic CRUD operations.

調整頁面設計,並加入新的客戶和訂單的方格Adjust the page design and add grids for new customers and orders

Visual Studio 所產生的預設排列方式不適合您的應用程式,因此您會在 XAML 中,以手動方式進行一些變更。The default arrangement produced by Visual Studio is not ideal for your application, so you'll make some changes manually in the XAML. 您也會需要某些 「 表單 」 (也就是實際上方格) 可讓使用者加入新的客戶或訂單。You also need some "forms" (which are actually Grids) to enable the user to add a new customer or order. 為了能夠加入新的客戶和訂單,您需要一組個別的文字方塊不是資料繫結至CollectionViewSourceIn order to be able to add a new customer and order, you need a separate set of text boxes that are not data-bound to the CollectionViewSource. 您會控制哪些使用者會看到在任何指定時間的處理常式方法中設定的 Visible 屬性的方格。You'll control which grid the user sees at any given time by setting the Visible property in the handler methods. 最後,您可以新增 [刪除] 按鈕,讓使用者刪除個別訂單的訂單方格中的每個資料列。Finally, you add a Delete button to each row in the Orders grid to enable the user to delete an individual order.

首先,新增至這些樣式Windows.Resources中的項目MainWindow.xaml:First, add these styles to the Windows.Resources element in MainWindow.xaml:

<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>

接下來,有了此標記取代整個外部的方格:Next, replace the entire outer Grid with this 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>

加入按鈕,瀏覽、 新增、 更新和刪除Add buttons to navigate, add, update, and delete

在 Windows Forms 應用程式,您取得 BindingNavigator 物件具有按鈕瀏覽資料庫中的資料列,並執行基本 CRUD 作業。In Windows Forms applications, you get a BindingNavigator object with buttons for navigating through rows in a database and doing basic CRUD operations. WPF 不會提供 BindingNavigator,但很輕易地建立一個。WPF does not provide a BindingNavigator, but it is easy enough to create one. 您這麼做的水平的 StackPanel 內的按鈕,並會繫結至程式碼後置中方法的命令相關聯的按鈕。You do that with buttons inside a horizontal StackPanel, and associate the buttons with Commands that are bound to methods in the code behind.

有個四部分的命令邏輯:(1) 命令、 (2) 的繫結、 (3) 按鈕,以及 (4) 命令中的處理常式程式碼後置。There are fours parts to the command logic: (1) the commands, (2) the bindings, (3) the buttons, and (4) the command handlers in the code-behind.

在 XAML 中新增命令、 繫結和按鈕Add commands, bindings, and buttons in XAML

  1. 首先,新增中的命令MainWindow.xaml檔案內Windows.Resources項目:First, add the commands in the MainWindow.xaml file inside the Windows.Resources element:

    <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. CommandBinding 對應RoutedUICommand事件,以在程式碼後置中的方法。A CommandBinding maps a RoutedUICommand event to a method in the code behind. 新增這CommandBindings之後的項目Windows.Resources結尾標記:Add this CommandBindings element after the Windows.Resources closing tag:

    <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. 現在,加入StackPanel,導覽中,新增、 刪除和更新 按鈕。Now, add the StackPanel with the navigation, add, delete, and update buttons. 首先,新增到此樣式Windows.Resources:First, add this style to Windows.Resources:

    <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>
    

    第二,貼上此程式碼後方RowDefinitions外部Grid項目中,XAML 頁面的上方:Second, paste this code just after the RowDefinitions for the outer Grid element, toward the top of the XAML page:

    <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>
    

將命令處理常式新增至 MainWindow 類別Add command handlers to the MainWindow class

程式碼後置是最基本的新增和刪除方法除外。The code-behind is minimal except for the add and delete methods. 瀏覽執行 CollectionViewSource 的 [檢視] 屬性上呼叫方法。Navigation is performed by calling methods on the View property of the CollectionViewSource. DeleteOrderCommandHandler示範如何執行串聯刪除順序。The DeleteOrderCommandHandler shows how to perform a cascade delete on an order. 我們必須先刪除與它相關聯的訂單明細。We have to first delete the Order_Details that are associated with it. UpdateCommandHandler將新的客戶或訂單加入至集合中,否則就只是使用者所做的文字方塊中所做的變更會更新現有的客戶或訂單。The UpdateCommandHandler adds a new customer or order to the collection, or else just updates an existing customer or order with the changes that the user made in the text boxes.

這些處理常式方法加入 MainWindow 類別中MainWindow.xaml.csAdd these handler methods to the MainWindow class in MainWindow.xaml.cs. 如果您針對 Customers 資料表的 CollectionViewSource 會有不同的名稱,您需要調整中每一種方法的名稱:If your CollectionViewSource for the Customers table has a different name, then you need to adjust the name in each of these methods:

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.  

        Order newOrder = new Order()
        {
            OrderDate = add_orderDatePicker.SelectedDate,
            RequiredDate = add_requiredDatePicker.SelectedDate,
            ShippedDate = add_shippedDatePicker.SelectedDate
        };

        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;
    }

    Order newOrder = new Order();
    newOrder.CustomerID = cust.CustomerID;

    // Get address and other mostly constant fields from   
    // an existing order, if one exists  
    var coll = custViewSource.Source as IEnumerable<Customer>;
    var lastOrder = (from c in coll
                     from ord in c.Orders
                     select ord).LastOrDefault();
    if (lastOrder != null)
    {
        newOrder.ShipAddress = lastOrder.ShipAddress;
        newOrder.ShipCity = lastOrder.ShipCity;
        newOrder.ShipCountry = lastOrder.ShipCountry;
        newOrder.ShipName = lastOrder.ShipName;
        newOrder.ShipPostalCode = lastOrder.ShipPostalCode;
        newOrder.ShipRegion = lastOrder.ShipRegion;
    }

    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);
}

執行應用程式Run the application

若要開始偵錯,請按 F5To start debugging, press F5. 您應該會看到客戶和訂單資料,在方格中,填入,並瀏覽按鈕應可正常運作。You should see customer and order data populated in the grid, and the navigation buttons should work as expected. 按一下 認可若要將新的客戶或訂單加入至模型之後您所輸入的資料。Click on Commit to add a new customer or order to the model after you have entered the data. 按一下 取消心意不想新客戶或新的訂單,而不儲存資料。Click on Cancel to back out of a new customer or new order form without saving the data. 您可以對現有的 customers 和 orders,直接在 [文字] 方塊中的編輯,以及這些變更會自動寫入至模型。You can make edits to existing customers and orders directly in the text boxes, and those changes are written to the model automatically.

另請參閱See also