共用方式為


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

本教學課程會建立簡單的應用程式來管理客戶清單。 如此一來,它會針對UWP中的企業應用程式引進一系列基本概念。 您將瞭解如何:

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

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

工作應用程式的主頁面

先決條件

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

備註

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

第 1 部分:感興趣的程式代碼

如果您在開啟應用程式之後立即執行,您會在空白畫面頂端看到一些按鈕。 雖然您無法看到,但應用程式已配備了一個包含幾個測試客戶的本機 SQLite 資料庫。 從這裡開始,您將從實作UI控制項來顯示這些客戶,然後繼續對資料庫新增作業。 開始之前,以下是您將工作的地方。

瀏覽次數

CustomerListPage.xaml 是應用程式的 View,它會定義本教學課程中單一頁面的 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. 從「Solution Explorer」開啟 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 資料庫擷取測試 Customer 數據。

  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 方法的呼叫。 這可讓其連絡儲存庫以擷取可列舉的客戶物件集合。 然後,它會將它們剖析成個別物件,再將它們新增至其內部 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,用來保存新建立的客戶。

    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. 將下列程式代碼行新增為 setter 中 AddNewCustomer的最後一行:

    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
  • 請提供遠端資料庫的網址,並放入 Constants.cs
  • 請將資料庫的連接字串提供給 Constants.cs
  • 將您的應用程式與 Microsoft 市集產生關聯。
  • Service 項目複製到您的應用程式,並將其部署至 Azure。

認證

您必須建立按鈕來啟動驗證流程,以及彈出視窗或個別頁面來收集用戶的資訊。 建立之後,您必須提供程式碼來要求使用者的資訊,並使用它來取得存取令牌。 客戶訂單資料庫範例使用 WebAccountManager 函式庫封裝對 Microsoft Graph 的呼叫,以獲取令牌並處理到 Azure Active Directory (AAD) 帳戶的身份驗證。

REST 呼叫

您不需要修改我們在本教學課程中新增的任何程序代碼,才能實作 REST 呼叫。 相反地,您必須執行下列動作:

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

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