Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве создается простое приложение для управления списком клиентов. При этом в нем представлен выбор основных концепций корпоративных приложений в UWP. Вы узнаете, как:
- Реализуйте операции создания, чтения, обновления и удаления в локальной базе данных SQL.
- Добавьте сетку данных для отображения и изменения данных клиента в пользовательском интерфейсе.
- Упорядочение элементов пользовательского интерфейса в базовом макете формы.
Отправной точкой этого руководства является одностраничное приложение с минимальным пользовательским интерфейсом и функциональностью, основанное на упрощенной версии примера приложения Customer Orders Database. Он написан на C# и XAML, и мы ожидаем, что у вас есть базовое знакомство с обоими языками.
Предпосылки
- Убедитесь, что у вас есть последняя версия Visual Studio и пакета SDK для Windows
- Склонируйте или скачайте образец руководства по базе данных клиентской
После клонирования или скачивания репозитория, вы можете изменить проект, открыв CustomerDatabaseTutorial.sln с помощью Visual Studio.
Замечание
Это руководство основано на примере базы данных заказов клиентов, которая недавно была обновлена для использования WinUI и пакета SDK для приложений Windows. До обновления этого руководства и кода между двумя примерами будут различия.
Часть 1. Код интереса
Если вы запускаете приложение сразу после открытия, вы увидите несколько кнопок в верхней части пустого экрана. Хотя это не видно для вас, приложение уже включает локальную базу данных SQLite, подготовленную для нескольких тестовых клиентов. Здесь вы начните с реализации элемента управления пользовательского интерфейса для отображения этих клиентов, а затем перейдите к добавлению операций в базе данных. Прежде чем начать, вот где вы будете работать.
Представления
CustomerListPage.xaml — это представление приложения, определяющее пользовательский интерфейс для одной страницы в этом руководстве. В любой момент, когда вам нужно добавить или изменить визуальный элемент в пользовательском интерфейсе, вы сделаете это в этом файле. В этом руководстве описано, как добавить следующие элементы:
-
RadDataGrid для отображения и редактирования ваших клиентов. - StackPanel для установки начальных значений для нового клиента.
ViewModels
ViewModels\CustomerListPageViewModel.cs находится основная логика приложения. Каждое действие пользователя, выполняемое в представлении, будет передано в этот файл для обработки. В этом руководстве вы добавите новый код и реализуйте следующие методы:
- CreateNewCustomerAsync, который инициализирует новый объект CustomerViewModel.
- DeleteNewCustomerAsync, который удаляет добавляемого клиента перед его отображением в пользовательском интерфейсе.
- DeleteAndUpdateAsync, которая обрабатывает логику кнопки удаления.
- GetCustomerListAsync, который получает список клиентов из базы данных.
- SaveInitialChangesAsync, который добавляет в базу данных новую информацию о клиенте.
- UpdateCustomersAsync, которая обновляет пользовательский интерфейс, чтобы отразить любых клиентов, добавленных или удаленных.
CustomerViewModel — это оболочка для информации клиента, которая отслеживает, была ли она недавно изменена. Вам не нужно добавлять ничего в этот класс, но некоторые из кода, который вы добавите в другое место, будет ссылаться на него.
Для получения дополнительной информации о том, как построен пример, ознакомьтесь с обзором структуры приложения.
Часть 2. Добавление DataGrid
Прежде чем приступить к работе с данными клиента, необходимо добавить элемент управления пользовательского интерфейса для отображения этих клиентов. Для этого мы будем использовать готовый элемент управления RadDataGrid. Пакет NuGet Telerik.UI.for.UniversalWindowsPlatform уже включен в этот проект. Давайте добавим сетку в наш проект.
Откройте Views\CustomerListPage.xaml из обозревателя решений. Добавьте следующую строку кода в тег страницы
, чтобы объявить сопоставление с пространством имен Telerik, содержащим сетку данных. xmlns:telerikGrid="using:Telerik.UI.Xaml.Controls.Grid"
Под CommandBar в главной RelativePanel представления добавьте элемент управления 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>
Вы добавили сетку данных, но она должна отображать данные. Добавьте в него следующие строки кода:
ItemsSource="{x:Bind ViewModel.Customers}" UserEditMode="Inline"
Теперь, когда вы определили источник данных для отображения, RadDataGrid будет обрабатывать большую часть логики пользовательского интерфейса. Тем не менее, если вы запускаете проект, вы по-прежнему не увидите никаких данных на экране. Это связано с тем, что ViewModel пока не загружает его.
Часть 3. Изучение клиентов
При инициализации ViewModels\CustomerListPageViewModel.cs вызывает метод GetCustomerListAsync. Этот метод должен получить тестовые данные клиента из базы данных SQLite, включенной в руководство.
В 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)); } }); }
Метод GetCustomerListAsync вызывается при загрузке ViewModel, но до этого шага он ничего не делал. Мы добавили вызов метода GetAsync в репозитории SqlCustomerRepository. Это позволяет связаться с репозиторием для получения перечисленной коллекции объектов Customer. Затем он разбирает их на отдельные объекты, прежде чем добавлять их во внутренний ObservableCollection, чтобы их можно было отобразить и изменить.
Запустите приложение. Теперь вы увидите сетку данных, отображающую список клиентов.
Часть 4. Изменение клиентов
Вы можете изменять записи в сетке данных, дважды щелкнув по ним, но необходимо удостовериться, что все изменения, внесенные в пользовательский интерфейс, также вносятся в вашу коллекцию клиентов в коде обратной стороны. Это означает, что необходимо реализовать двусторонняя привязка данных. Если вы хотите получить дополнительные сведения об этом, ознакомьтесь с нашим введением в привязку данных.
Сначала объявите, что ViewModels\CustomerListPageViewModel.cs реализует интерфейс INotifyPropertyChanged:
public class CustomerListPageViewModel : INotifyPropertyChanged
Затем в основной текст класса добавьте следующее событие и метод:
public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Метод OnPropertyChanged упрощает вызов события PropertyChanged, которое необходимо для двусторонней привязки данных.
Обновите сеттер для SelectedCustomer, вызвав эту функцию:
public CustomerViewModel SelectedCustomer { get => _selectedCustomer; set { if (_selectedCustomer != value) { _selectedCustomer = value; OnPropertyChanged(); } } }
В Views\CustomerListPage.xamlдобавьте свойство SelectedCustomer в сетку данных.
SelectedItem="{x:Bind ViewModel.SelectedCustomer, Mode=TwoWay}"
Это связывает выбор пользователя в таблице данных с соответствующим объектом Customer в коде, связанном с пользовательским интерфейсом. Режим привязки TwoWay позволяет изменениям, внесенным в пользовательский интерфейс, отражаться на этом объекте.
Запустите приложение. Теперь вы можете увидеть клиентов, отображаемых в сетке, и внести изменения в базовые данные через пользовательский интерфейс.
Часть 5. Обновление клиентов
Теперь, когда вы можете просматривать и изменять клиентов, вам потребуется отправить изменения в базу данных и извлечь все обновления, внесенные другими пользователями.
Вернитесь к 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(); }
Этот код использует свойство IsModifiedViewModels\CustomerViewModel.cs, которое автоматически обновляется при изменении клиента. Это позволяет избежать ненужных вызовов и отправлять только изменения от обновленных клиентов в базу данных.
Часть 6. Создание нового клиента
Добавление нового клиента представляет проблему, так как клиент будет отображаться как пустая строка, если добавить ее в пользовательский интерфейс, прежде чем предоставлять значения для его свойств. Это не проблема, но здесь мы упростим настройку начальных значений клиента. В этом руководстве мы добавим простую сворачиваемую панель, но если у вас есть дополнительные сведения для добавления, можно создать отдельную страницу для этой цели.
Обновление программной части
Добавьте новое частное поле и общедоступное свойство в ViewModels\CustomerListPageViewModel.cs. Это будет использоваться для управления тем, отображается ли панель.
private bool _addingNewCustomer = false; public bool AddingNewCustomer { get => _addingNewCustomer; set { if (_addingNewCustomer != value) { _addingNewCustomer = value; OnPropertyChanged(); } } }
Добавьте новое общедоступное свойство в ViewModel, и обратное значение ДобавлениеНовогоКлиента. Это будет использоваться для отключения обычных кнопок панели команд, когда панель видна.
public bool EnableCommandBar => !AddingNewCustomer;
Теперь вам потребуется способ отображения сворачиваемой панели и создания клиента для редактирования внутри него.
Добавьте новое частное и общедоступное свойство в ViewModel, чтобы сохранить только что созданного клиента.
private CustomerViewModel _newCustomer; public CustomerViewModel NewCustomer { get => _newCustomer; set { if (_newCustomer != value) { _newCustomer = value; OnPropertyChanged(); } } }
Обновите метод CreateNewCustomerAsync, чтобы создать нового клиента, добавить его в репозиторий и задать его в качестве выбранного клиента:
public async Task CreateNewCustomerAsync() { CustomerViewModel newCustomer = new CustomerViewModel(new Models.Customer()); NewCustomer = newCustomer; await App.Repository.Customers.UpsertAsync(NewCustomer.Model); AddingNewCustomer = true; }
Обновите метод SaveInitialChangesAsync, чтобы добавить недавно созданного клиента в репозиторий, обновить пользовательский интерфейс и закрыть панель.
public async Task SaveInitialChangesAsync() { await App.Repository.Customers.UpsertAsync(NewCustomer.Model); await UpdateCustomersAsync(); AddingNewCustomer = false; }
Добавьте следующую строку кода как последнюю строку в сеттере для AddingNewCustomer.
OnPropertyChanged(nameof(EnableCommandBar));
Это гарантирует, что EnableCommandBar автоматически обновляется всякий раз при изменении ДобавлениеНовогоКлиента.
Обновление пользовательского интерфейса
Вернитесь к Views\CustomerListPage.xamlи добавьте StackPanel со следующими свойствами между вашим CommandBar и вашей таблицей данных:
<StackPanel x:Name="newCustomerPanel" Orientation="Horizontal" x:Load="{x:Bind ViewModel.AddingNewCustomer, Mode=OneWay}" RelativePanel.Below="mainCommandBar"> </StackPanel>
Атрибут x:Load гарантирует, что эта панель отображается только при добавлении нового клиента.
Внесите следующее изменение в положение сетки данных, чтобы убедиться, что он перемещается вниз при появлении новой панели:
RelativePanel.Below="newCustomerPanel"
Обновите вашу StackPanel, добавив четыре элемента управления 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>
Добавьте простую кнопку на новую панель стека, чтобы сохранить только что созданного клиента:
<StackPanel> <!--Text boxes from step 3--> <AppBarButton x:Name="SaveNewCustomer" Click="{x:Bind ViewModel.SaveInitialChangesAsync}" Icon="Save"/> </StackPanel>
Обновите CommandBar, чтобы стандартные кнопки создания, удаления и обновления были отключены, когда панель стека отображается:
<CommandBar x:Name="mainCommandBar" HorizontalAlignment="Stretch" IsEnabled="{x:Bind ViewModel.EnableCommandBar, Mode=OneWay}" Background="AliceBlue"> <!--App bar buttons--> </CommandBar>
Запустите приложение. Теперь вы можете создать клиента и ввести данные на панели стека.
Часть 7. Удаление клиента
Удаление клиента является последней базовой операцией, которую необходимо реализовать. При удалении клиента, выбранного в сетке данных, необходимо немедленно вызвать UpdateCustomersAsync, чтобы обновить пользовательский интерфейс. Тем не менее, вам не нужно вызывать этот метод, если вы удаляете только что созданного клиента.
Перейдите к ViewModels\CustomerListPageViewModel.csи обновите метод DeleteAndUpdateAsync:
public async void DeleteAndUpdateAsync() { if (SelectedCustomer != null) { await App.Repository.Customers.DeleteAsync(_selectedCustomer.Model.Id); } await UpdateCustomersAsync(); }
В 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>
В ViewModels\CustomerListPageViewModel.csобновите метод DeleteNewCustomerAsync, чтобы удалить нового клиента:
public async Task DeleteNewCustomerAsync() { if (NewCustomer != null) { await App.Repository.Customers.DeleteAsync(_newCustomer.Model.Id); AddingNewCustomer = false; } }
Запустите приложение. Теперь вы можете удалить клиентов в сетке данных или на панели стека.
клиента
Заключение
Поздравляю! С учетом всего этого приложение теперь имеет полный спектр локальных операций базы данных. Вы можете создавать, читать, обновлять и удалять клиентов в пользовательском интерфейсе, а эти изменения сохраняются в базе данных и сохраняются в разных запусках приложения.
Теперь, когда вы закончите, рассмотрите следующее:
- Если вы еще не сделали этого, ознакомьтесь с обзором структуры приложений для получения дополнительных сведений о том, почему приложение создано так.
- Ознакомьтесь с примером полной базы данных заказов клиентов, чтобы увидеть приложение, которое использовалось в этом руководстве.
Или если вы готовы к испытанию, вы можете продолжать...
Далее: подключение к удаленной базе данных
Мы предоставили пошаговое руководство по реализации этих вызовов для локальной базы данных SQLite. Но что делать, если вы хотите использовать удаленную базу данных, вместо этого?
Если вы хотите попробовать, вам потребуется собственная учетная запись Azure Active Directory (AAD) и возможность размещения собственного источника данных.
Необходимо добавить проверку подлинности, функции для обработки вызовов REST, а затем создать удаленную базу данных для взаимодействия. В полной примере базы данных заказов клиентов есть код, на который можно ссылаться для каждой необходимой операции.
Параметры и конфигурация
Необходимые шаги для подключения к собственной удаленной базе данных описаны в файле README примера. Вам потребуется выполнить следующие действия.
- Укажите идентификатор клиента учетной записи Azure для Constants.cs.
- Укажите URL-адрес удаленной базы данных для Constants.cs.
- Укажите строку подключения для базы данных Constants.cs.
- Свяжите приложение с Microsoft Store.
- Скопируйте проект службы в приложение и разверните его в Azure.
Аутентификация
Вам потребуется создать кнопку для запуска последовательности проверки подлинности, а также всплывающего окна или отдельной страницы для сбора сведений о пользователе. После создания этого необходимо предоставить код, который запрашивает сведения пользователя и использует их для получения токена доступа. Пример базы данных заказов клиентов оборачивает вызовы Microsoft Graph с помощью библиотеки WebAccountManager для получения токена и обработки аутентификации в учетной записи AAD.
- Логика проверки подлинности реализована в AuthenticationViewModel.cs.
- Процесс проверки подлинности отображается в пользовательском элементе управления AuthenticationControl.xaml.
Вызовы REST API
Чтобы реализовать вызовы REST, вам не нужно изменять любой код, добавленный в этом руководстве. Вместо этого вам потребуется выполнить следующие действия:
- Создайте новые реализации интерфейсов ICustomerRepository и интерфейсов ITutorialRepository, реализуя тот же набор функций через REST вместо SQLite. Вам потребуется сериализовать и десериализировать JSON и упаковать вызовы REST в отдельный класс httpHelper
, если это необходимо. Обратитесь к полному примеру для получения конкретной информации. - В App.xaml.csсоздайте новую функцию для инициализации репозитория REST и вызовите ее вместо sqliteDatabase при инициализации приложения. Опять же, см. полный пример.
После завершения всех трех этих действий вы сможете пройти проверку подлинности в учетной записи AAD через приложение. Вызовы REST к удаленной базе данных заменят локальные вызовы SQLite, но взаимодействие с пользователем должно совпадать. Если вы чувствуете себя еще более амбициозным, вы можете добавить страницу параметров, чтобы позволить пользователю динамически переключаться между двумя.