共用方式為


教學課程:建立客戶資料庫應用程式

本教學課程會建立一個簡單的應用程式來管理客戶清單。 為此,它會介紹 UWP 中企業應用程式的一系列基本概念。 您將學習如何:

  • 對本機 SQL 資料庫實作建立、讀取、更新和刪除作業。
  • 新增資料格,以在 UI 中顯示和編輯客戶資料。
  • 將 UI 元素排列在基本表單佈局中。

本教程以具有最少 UI 和功能的單頁應用程序作為開頭,以簡化的客戶訂單資料庫範例應用程式版本為基礎。 它是以 C# 和 XAML 撰寫,我們預期您已基本熟悉這兩種語言。

工作應用程式的主頁面

必要條件

複製/下載存放庫之後,就可以使用 Visual Studio 開啟 CustomerDatabaseTutorial.sln 來編輯專案。

注意

本教學課程是以客戶訂單資料庫範例為基礎,該範例最近已更新為使用 WinUI 和 Windows 應用程式 SDK。 在本教學課程和程式碼更新之前,這兩個範例之間將會存在差異。

第 1 部分:興趣程式碼

如果您在打開應用程式後立即運行,您會在空白畫面頂端看到幾個按鈕。 雖然您看不到,但該應用程式已經包含一個由幾位測試客戶佈建的本機 SQLite 資料庫。 從這裡開始,您將先實作一個 UI 控制項來顯示這些客戶,然後繼續新增針對資料庫的作業。 在開始之前,以下是您將執行動作的地方。

檢視

CustomerListPage.xaml 是應用程式的視圖,其定義本教學課程中單一頁面的 UI。 每當您需要在 UI 中新增或變更視覺元素時,都可以在此檔案中完成。 本教學將引導您新增以下元素:

  • RadDataGrid,用來顯示和編輯客戶。
  • StackPanel,可設定新客戶的初始值。

ViewModels

ViewModels\CustomerListPageViewModel.cs,這是應用程式基本邏輯所在的位置。 在視圖中執行的每個使用者動作都會傳遞到此檔案中進行處理。 在本教程中,您將添加一些新程式碼,並實作以下方法:

  • CreateNewCustomerAsync,初始化新的 CustomerViewModel 物件。
  • DeleteNewCustomerAsync,它會先移除新客戶,再將其顯示在 UI 中。
  • DeleteAndUpdateAsync,其可處理刪除按鈕的邏輯。
  • GetCustomerListAsync,其會從資料庫擷取客戶清單。
  • SaveInitialChangesAsync,其會將新的客戶資訊新增至資料庫。
  • UpdateCustomersAsync,其會重新整理 UI,以反映任何新增或刪除的客戶。

CustomerViewModel,是客戶資訊的包裝函式,可追蹤它是否最近修改過。 您不需要向此類別添加任何內容,但您在其他地方添加的部分程式碼將引用它。

有關如何建構範例的詳細資訊,請參閱應用程序結構概觀

第 2 部分:新增 DataGrid

開始對客戶資料進行操作之前,您需要新增一個 UI 控制項來顯示這些客戶。 若要這樣做,我們將使用預先製作的第三方 RadDataGrid 控制項。 Telerik.UI.for.UniversalWindowsPlatform NuGet 套件已包含在此專案中。 讓我們將網格線新增至專案。

  1. 從「方案總管」開啟 Views\CustomerListPage.xaml。 在 Page 標籤中新增以下程式代碼行,以宣告對應至包含數據格的 Telerik 命名空間。

        xmlns:telerikGrid="using:Telerik.UI.Xaml.Controls.Grid"
    
  2. 在視圖的主要 RelativePanel 內的 CommandBar 下方,新增 RadDataGrid 控件,其中包含一些基本設定選項:

    <Grid
        x:Name="CustomerListRoot"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <RelativePanel>
            <CommandBar
                x:Name="mainCommandBar"
                HorizontalAlignment="Stretch"
                Background="AliceBlue">
                <!--CommandBar content-->
            </CommandBar>
            <telerikGrid:RadDataGrid
                x:Name="DataGrid"
                BorderThickness="0"
                ColumnDataOperationsMode="Flyout"
                GridLinesVisibility="None"
                GroupPanelPosition="Left"
                RelativePanel.AlignLeftWithPanel="True"
                RelativePanel.AlignRightWithPanel="True"
                RelativePanel.Below="mainCommandBar" />
        </RelativePanel>
    </Grid>
    
  3. 您已新增資料網格,但它需要資料才能顯示。 將以下程式碼行加入其中:

    ItemsSource="{x:Bind ViewModel.Customers}"
    UserEditMode="Inline"
    

    現在您已經定義了要顯示的資料來源,RadDataGrid 將為您處理大部分 UI 邏輯。 不過,如果您執行專案,仍然不會看到任何資料。 那是因為 ViewModel 尚未載入資料。

空白應用程式,沒有客戶

第 3 部分:閱讀客戶

初始化後,ViewModels\CustomerListPageViewModel.cs 會呼叫 GetCustomerListAsync 方法。 此方法需要從本教程中包含的 SQLite 資料庫檢索測試客戶資料。

  1. ViewModels\CustomerListPageViewModel.cs 中,使用下列程式碼更新 GetCustomerListAsync 方法:

    public async Task GetCustomerListAsync()
    {
        var customers = await App.Repository.Customers.GetAsync(); 
        if (customers == null)
        {
            return;
        }
        await DispatcherHelper.ExecuteOnUIThreadAsync(() =>
        {
            Customers.Clear();
            foreach (var c in customers)
            {
                Customers.Add(new CustomerViewModel(c));
            }
        });
    }
    

    載入 ViewModel 時會呼叫 GetCustomerListAsync 方法,但在此步驟之前,其不會執行任何動作。 在這裡,我們已在 Repository/SqlCustomerRepository 中新增 GetAsync 方法的呼叫。 這可讓其連絡存放庫以擷取 Customer 物件的可列舉集合。 然後,它會將它們剖析成個別物件,再將它們新增至其內部 ObservableCollection ,以便顯示和編輯它們。

  2. 執行您的應用程式 - 您現在會看到顯示客戶清單的資料格。

初始客戶清單

第 4 部分:編輯客戶

您可以按兩下資料格中的項目來進行編輯,但您必須確定您在 UI 中所做的任何變更也會對程式碼後置中的客戶集合進行變更。 這表示您必須實作雙向數據系結。 如果您想了解更多相關資訊,請參閱我們的數據系結簡介

  1. 首先,宣告 ViewModels\CustomerListPageViewModel.cs 實作 INotifyPropertyChanged 介面:

    public class CustomerListPageViewModel : INotifyPropertyChanged
    
  2. 然後,在類別的主體中,新增以下事件和方法:

    public event PropertyChangedEventHandler PropertyChanged;
    
    public void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    

    OnPropertyChanged 方法可讓您的 setter 輕鬆引發 PropertyChanged 事件,這對於雙向資料綁定是必要的。

  3. 使用下列函數呼叫更新 SelectedCustomer 的 setter:

    public CustomerViewModel SelectedCustomer
    {
        get => _selectedCustomer;
        set
        {
            if (_selectedCustomer != value)
            {
                _selectedCustomer = value;
                OnPropertyChanged();
            }
        }
    }
    
  4. Views\CustomerListPage.xaml 中,將 SelectedCustomer 屬性新增至您的數據格。

    SelectedItem="{x:Bind ViewModel.SelectedCustomer, Mode=TwoWay}"
    

    這會將資料網格中的使用者選擇與程式碼隱藏中對應的 Customer 物件相關聯。 TwoWay 綁定模式可讓您在 UI 中所做的變更反映在該物件上。

  5. 執行應用程式。 現在您可以查看網格中顯示的客戶,並透過 UI 對基礎資料進行變更。

在資料格中編輯客戶

第 5 部分:更新客戶

現在您可以查看和編輯客戶,您需要能夠將變更推送到資料庫,並提取其他人所做的任何更新。

  1. 返回 ViewModels\CustomerListPageViewModel.cs,然後流覽至 UpdateCustomersAsync 方法。 使用以下程式碼進行更新,將變更推送到資料庫並檢索任何新資訊:

    public async Task UpdateCustomersAsync()
    {
        foreach (var modifiedCustomer in Customers
            .Where(x => x.IsModified).Select(x => x.Model))
        {
            await App.Repository.Customers.UpsertAsync(modifiedCustomer);
        }
        await GetCustomerListAsync();
    }
    

    此程式代碼會利用 ViewModels\CustomerViewModel.csIsModified 屬性,每當客戶變更時就會自動更新。 這可讓您避免不必要的呼叫,並只將更新的客戶變更推送至資料庫。

第 6 部分:建立新客戶

新增客戶是一項挑戰,因為如果您在為其屬性提供值之前將其新增至 UI,則該客戶將顯示為空白行。 這不是個問題,但在這裡,我們將能更輕鬆設定客戶的初始值。 在本教學課程中,我們將新增簡單的可折疊面板,但如果您有更多資訊要新增,您可以為此一個單獨的頁面。

更新程式碼後置

  1. 將新的私人欄位和公用屬性新增至 ViewModels\CustomerListPageViewModel.cs。 這會用來控制面板是否可見。

    private bool _addingNewCustomer = false;
    
    public bool AddingNewCustomer
    {
        get => _addingNewCustomer;
        set
        {
            if (_addingNewCustomer != value)
            {
                _addingNewCustomer = value;
                OnPropertyChanged();
            }
        }
    }
    
  2. 在 ViewModel 新增一個新的公用屬性,該屬性與 AddingNewCustomer 的值相反。 當面板可見時,這將用於停用一般命令列按鈕。

    public bool EnableCommandBar => !AddingNewCustomer;
    

    現在您需要一種方法來顯示可折疊面板,並建立一個客戶以在其中進行編輯。

  3. 在 ViewModel 新增一個新的私人 fiend 和公用屬性,以儲存新建立的客戶。

    private CustomerViewModel _newCustomer;
    
    public CustomerViewModel NewCustomer
    {
        get => _newCustomer;
        set
        {
            if (_newCustomer != value)
            {
                _newCustomer = value;
                OnPropertyChanged();
            }
        }
    }
    
  4. 更新 CreateNewCustomerAsync 方法以建立新的客戶、將其新增至存放庫,並將其設為已選取的客戶:

    public async Task CreateNewCustomerAsync()
    {
        CustomerViewModel newCustomer = new CustomerViewModel(new Models.Customer());
        NewCustomer = newCustomer;
        await App.Repository.Customers.UpsertAsync(NewCustomer.Model);
        AddingNewCustomer = true;
    }
    
  5. 更新 SaveInitialChangesAsync 方法,將新建立的客戶新增至存放庫、更新 UI,然後關閉面板。

    public async Task SaveInitialChangesAsync()
    {
        await App.Repository.Customers.UpsertAsync(NewCustomer.Model);
        await UpdateCustomersAsync();
        AddingNewCustomer = false;
    }
    
  6. 將以下程式碼行新增為 AddingNewCustomer 中 setter 的最後一行:

    OnPropertyChanged(nameof(EnableCommandBar));
    

    這將確保每當 AddingNewCustomer 發生變更時,EnableCommandBar 都會自動更新。

更新 UI

  1. 導覽回 Views\CustomerListPage.xaml,並在 CommandBar 和資料網格之間新增具有以下屬性的 StackPanel

    <StackPanel
        x:Name="newCustomerPanel"
        Orientation="Horizontal"
        x:Load="{x:Bind ViewModel.AddingNewCustomer, Mode=OneWay}"
        RelativePanel.Below="mainCommandBar">
    </StackPanel>
    

    x:Load 屬性可確保只有在您新增客戶時,才會顯示此面板。

  2. 對資料網格的位置進行以下更改,以確保它在新面板出現時向下移動:

    RelativePanel.Below="newCustomerPanel"
    
  3. 使用四個 TextBox 控制件更新堆疊面板。 它們將綁定到新客戶的各個屬性,並可讓您在將其新增至資料網格之前編輯其值。

    <StackPanel
        x:Name="newCustomerPanel"
        Orientation="Horizontal"
        x:Load="{x:Bind ViewModel.AddingNewCustomer, Mode=OneWay}"
        RelativePanel.Below="mainCommandBar">
        <TextBox
            Header="First name"
            PlaceholderText="First"
            Margin="8,8,16,8"
            MinWidth="120"
            Text="{x:Bind ViewModel.NewCustomer.FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox
            Header="Last name"
            PlaceholderText="Last"
            Margin="0,8,16,8"
            MinWidth="120"
            Text="{x:Bind ViewModel.NewCustomer.LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox
            Header="Address"
            PlaceholderText="1234 Address St, Redmond WA 00000"
            Margin="0,8,16,8"
            MinWidth="280"
            Text="{x:Bind ViewModel.NewCustomer.Address, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox
            Header="Company"
            PlaceholderText="Company"
            Margin="0,8,16,8"
            MinWidth="120"
            Text="{x:Bind ViewModel.NewCustomer.Company, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </StackPanel>
    
  4. 在新的堆疊面板中新增一個簡單的按鈕,以儲存新建立的客戶:

    <StackPanel>
        <!--Text boxes from step 3-->
        <AppBarButton
            x:Name="SaveNewCustomer"
            Click="{x:Bind ViewModel.SaveInitialChangesAsync}"
            Icon="Save"/>
    </StackPanel>
    
  5. 更新 CommandBar,以便當堆疊面板可見時停用一般建立、刪除和更新按鈕:

    <CommandBar
        x:Name="mainCommandBar"
        HorizontalAlignment="Stretch"
        IsEnabled="{x:Bind ViewModel.EnableCommandBar, Mode=OneWay}"
        Background="AliceBlue">
        <!--App bar buttons-->
    </CommandBar>
    
  6. 執行應用程式。 您現在可以建立客戶,並在堆疊面板中輸入其數據。

建立新客戶

第 7 部分:刪除客戶

刪除客戶是您需要實作的最後一個基本作業。 當您刪除在資料格中選取的客戶時,您需要立即呼叫 UpdateCustomersAsync 以更新 UI。 但是,如果您要刪除剛剛建立的客戶,則無需呼叫該方法。

  1. 流覽至 ViewModels\CustomerListPageViewModel.cs,並更新 DeleteAndUpdateAsync 方法:

    public async void DeleteAndUpdateAsync()
    {
        if (SelectedCustomer != null)
        {
            await App.Repository.Customers.DeleteAsync(_selectedCustomer.Model.Id);
        }
        await UpdateCustomersAsync();
    }
    
  2. Views\CustomerListPage.xaml 中,更新用於新增客戶的堆疊面板,使其包含第二個按鈕:

    <StackPanel>
        <!--Text boxes for adding a new customer-->
        <AppBarButton
            x:Name="DeleteNewCustomer"
            Click="{x:Bind ViewModel.DeleteNewCustomerAsync}"
            Icon="Cancel"/>
        <AppBarButton
            x:Name="SaveNewCustomer"
            Click="{x:Bind ViewModel.SaveInitialChangesAsync}"
            Icon="Save"/>
    </StackPanel>
    
  3. ViewModels\CustomerListPageViewModel.cs,更新 DeleteNewCustomerAsync 方法來刪除新客戶:

    public async Task DeleteNewCustomerAsync()
    {
        if (NewCustomer != null)
        {
            await App.Repository.Customers.DeleteAsync(_newCustomer.Model.Id);
            AddingNewCustomer = false;
        }
    }
    
  4. 執行應用程式。 您現在可以在資料格內或堆疊面板中刪除客戶。

刪除新客戶

結論

恭喜! 完成這一切之後,您的應用程式現在已擁有完整的本機資料庫作業。 您可以在 UI 內建立、讀取、更新和刪除客戶,這些變更會儲存至您的資料庫,並會在應用程式的不同啟動中持續存在。

現在您已完成整個流程,請考慮下列事項:

或者,如果您準備好迎接挑戰,您可以繼續前進...

進一步:連線至遠端資料庫

我們已逐步解說如何針對本機 SQLite 資料庫實作這些呼叫。 但如果您想要改用遠端資料庫,該怎麼辦?

如果您想嘗試一下,您需要自己的 Azure Active Directory (AAD) 帳戶,以及託管資料來源的能力。

您需要新增驗證、處理 REST 呼叫的函數,然後建立一個遠端資料庫進行互動。 完整的客戶訂單資料庫範例中有程式碼,您可以參考每個必要的作業。

設定與組態

範例的自述文件中詳細說明了連接到您遠端資料庫的必要步驟。 您需要執行下列作業:

  • 將您的 Azure 帳戶用戶端識別碼提供給 Constants.cs
  • 將遠端資料庫的 URL 提供給 Constants.cs
  • Constants.cs 提供資料庫的連線字串。
  • 將您的應用程式與 Microsoft Store 關聯。
  • 服務專案複製到您的應用程式中,並將其部署到 Azure。

驗證

您需要建立一個按鈕來啟動驗證序列,並建立一個快顯視窗或單獨的頁面來收集使用者資訊。 建立之後,您必須提供程式碼來要求使用者的資訊,並使用其來取得存取令牌。 客戶訂單資料庫範例會使用 WebAccountManager 程式庫包裝 Microsoft Graph 呼叫,以取得令牌並處理 AAD 帳戶的驗證。

REST 呼叫

您無需修改我們在本教程中新增的任何程式碼即可實作 REST 呼叫。 但您需要執行下列作業:

  • 建立 ICustomerRepositoryITutorialRepository 介面的新實作,透過 REST 而不是 SQLite 實作相同的函數集。 您需要序列化和反序列化 JSON,並且如果需要,可以將 REST 呼叫包裝在單獨的 HttpHelper 類別中。 有關詳細資訊,請參閱完整範例
  • App.xaml.cs 中,建立一個新函數來初始化 REST 儲存庫,並在初始化應用程式時呼叫它,而不是 SqliteDatabase。 同樣地,請參閱完整的範例

完成上述三個步驟之後,您應該能夠透過應用程式對 AAD 帳戶進行驗證。 對遠端資料庫的 REST 呼叫將會取代本機 SQLite 呼叫,但使用者體驗應該是相同的。 如果您想更進一步,則可以新增設定頁面,讓使用者在兩者之間動態切換。