В первой и второй частях мы использовали Entity Framework для создания модели, отслеживающей идеи для другого приложения, сгенерировали файл базы данных .sdf, сгенерировали классы данных, а затем исправили ошибки в классе, чтобы он работал в Windows Phone. В этой части мы добавим некоторую структуру в наше приложение, настроим БД при первом запуске и добавим некоторые данные по умолчанию в некоторые таблицы. Затем, наконец, мы создадим пару представлений для отображения информации в базе данных.
Основываясь на отзывах, я хотел бы уточнить, что на данный момент мы закончили с использованием Entity Framework и используем LINQ to SQL для управления базой данных, которую мы использовали для разработки EF в Части 1.
Вы можете получить исходный код здесь.
Часть 3: Использование классов данных в приложении Windows Phone
Теперь, когда у нас есть сгенерированные классы в нашем проекте, пришло время их использовать. Нам нужно сначала немного настроить. Во второй части мы создали папку с названием Models. Это часть шаблона проектирования, который рекомендуется для всех, кроме самых простых приложений WP7. Мы будем использовать этот шаблон в нашем приложении.
Первое, что мы сделаем, это добавим в проект AppTracker.WP папку с именем Views.
Теперь мы собираемся создать класс для обработки данных по умолчанию в базе данных. Добавьте папку с именем DefaultData в проект AppTracker.WP. В нем добавьте класс DefaultData.cs. В этот класс мы включаем функции, которые:
проверяют, существует ли база данных, и удаляют ее при необходимости. Я использую это, чтобы облегчить первоначальное создание и повторное создание БД. Полезно, если вы хотите добавить опцию сброса.
public bool CreateDatabase(bool deleteExisting = false) { try { if (_context.DatabaseExists()) { if(deleteExisting) { _context.DeleteDatabase(); } else { return false; } } _context.CreateDatabase(); return true; } catch (Exception ex) { if (System.Diagnostics.Debugger.IsAttached) { MessageBox.Show(ex.Message); } return false; } } Populate 5 tables with default data: public bool PopulateStatusTable() { try { var statuses = new List<Status>(); var status = new Status { Id = 1, Name = "In Progress", Description = "Description Description Description Description Description" }; statuses.Add(status); status = new Status { Id = 2, Name = "Games", Description = "Description Description Description Description Description" }; statuses.Add(status); status = new Status { Id = 3, Name = "Other", Description = "Description Description Description Description Description" }; statuses.Add(status); _context.Status.InsertAllOnSubmit(statuses); _context.SubmitChanges(); return true; } catch (Exception ex) { if (System.Diagnostics.Debugger.IsAttached) { MessageBox.Show(ex.Message); } return false; } } public bool PopulatePlatformsTable() { try { var platforms = new List<Platform>(); var platform = new Platform { Id = 1, Name = "Windows Phone", Description = "Description Description Description Description Description" }; platforms.Add(platform); platform = new Platform { Id = 2, Name = "Android", Description = "Description Description Description Description Description" }; platforms.Add(platform); platform = new Platform { Id = 3, Name = "iOS", Description = "Description Description Description Description Description" }; platforms.Add(platform); _context.Platforms.InsertAllOnSubmit(platforms); _context.SubmitChanges(); return true; } catch (Exception ex) { if (System.Diagnostics.Debugger.IsAttached) { MessageBox.Show(ex.Message); } return false; } } public bool PopulateTagsTable() { try { var tags = new List<Tag>(); var category = new Tag { Id = 1, Name = "Tag 1", Description = "Description Description Description Description Description" }; tags.Add(category); category = new Tag { Id = 2, Name = "Tag 2", Description = "Description Description Description Description Description" }; tags.Add(category); category = new Tag { Id = 3, Name = "Tag 3", Description = "Description Description Description Description Description" }; tags.Add(category); _context.Tags.InsertAllOnSubmit(tags); _context.SubmitChanges(); return true; } catch (Exception ex) { if (System.Diagnostics.Debugger.IsAttached) { MessageBox.Show(ex.Message); } return false; } } public bool PopulateIdeasTable() { try { var ideas = new List<Idea>(); var idea = new Idea { Id = 1, Name = "Idea 1", Description = "Description Description Description Description Description", CategoryId = 1, StatusId = 1, DateAdded = DateTime.Now, DateUpdated = DateTime.Now }; ideas.Add(idea); idea = new Idea { Id = 2, Name = "Idea 2", Description = "Description Description Description Description Description", CategoryId = 1, StatusId = 1, DateAdded = DateTime.Now, DateUpdated = DateTime.Now }; ideas.Add(idea); idea = new Idea { Id = 3, Name = "Idea 3", Description = "Description Description Description Description Description", CategoryId = 1, StatusId = 1, DateAdded = DateTime.Now, DateUpdated = DateTime.Now}; ideas.Add(idea); _context.Ideas.InsertAllOnSubmit(ideas); _context.SubmitChanges(); return true; } catch (Exception ex) { if (System.Diagnostics.Debugger.IsAttached) { MessageBox.Show(ex.Message); } return false; } }
Теперь, когда у нас есть способ заполнить таблицы, давайте сделаем это. Хотя для этого есть несколько мест, я предпочитаю использовать конструктор файла MainViewModel.cs. Это гарантирует, что БД заполнена при запуске приложения.
private const string ConnectionString = @"isostore:/AppTrackerDatabase.sdf";
private AppTrackerDataContext _context = new AppTrackerDataContext(ConnectionString);
public MainViewModel() { try { if (!_context.DatabaseExists()) { // create database if it does not exist var dd = new DefaultData.DefaultData(_context); if (dd.CreateDatabase(true)) { if (Debugger.IsAttached) { MessageBox.Show("Database created."); } } else { if (Debugger.IsAttached) { MessageBox.Show("Error creating database"); } } if (dd.PopulateCategoriesTable() && dd.PopulatePlatformsTable() && dd.PopulateStatusTable() && dd.PopulateTagsTable() && dd.PopulateIdeasTable())) { if (Debugger.IsAttached) { MessageBox.Show("Tables populated"); } } else { if (Debugger.IsAttached) { MessageBox.Show("Error populating tables."); } } } else { if (Debugger.IsAttached) { MessageBox.Show("Database Exists."); } } } catch (Exception ex ) { if (Debugger.IsAttached) { MessageBox.Show(ex.Message); } } }
Теперь мы убедились, что свойство Items в MainViewModel вызывает событие PropertyChanged, поэтому пользовательский интерфейс обновляется.
private ObservableCollection _ideas; public ObservableCollection Ideas { get { return _ideas; } set { if (value != _ideas) { _ideas = value; NotifyPropertyChanged("Ideas"); } } }
Затем мы обновляем функцию LoadData, чтобы извлечь все записи Idea и загрузить их в коллекцию Items ObservableCollection. Эта загрузка вызывает событие PropertyChanged и вызывает обновление пользовательского интерфейса.
public void LoadData() { var ideas = _context.Ideas.Where(i => i.Id != 0); Ideas = new ObservableCollection(ideas.ToList()); this.IsDataLoaded = true; }
Затем мы обновляем файл MainPage.xaml для включения информации о CategoryId и StatusId. Я не буду освещать привязку данных в этом посте, но сделаю это в ближайшем будущем.
<ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding Ideas}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Margin="0,0,0,17" Width="432" Height="200"> <TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/> <TextBlock Text="{Binding Description}" TextWrapping="Wrap" Margin="12,-6,12,5" Style="{StaticResource PhoneTextSubtleStyle}"/> <StackPanel Orientation="Horizontal"> <TextBlock Text="CategoryId: " TextWrapping="Wrap" Margin="12,-6,12,5" Style="{StaticResource PhoneTextSubtleStyle}" Width="122" /> <TextBlock Text="{Binding CategoryId}" TextWrapping="Wrap" Margin="12,-6,12,5" Style="{StaticResource PhoneTextSubtleStyle}" Width="193" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="StatusId: " TextWrapping="Wrap" Margin="12,-6,12,5" Style="{StaticResource PhoneTextSubtleStyle}" Width="122" /> <TextBlock Text="{Binding StatusId}" TextWrapping="Wrap" Margin="12,-6,12,5" Style="{StaticResource PhoneTextSubtleStyle}"/> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
Теперь, если мы запустим проект, мы увидим страницу с 3-мя идеями.
На данный момент у нас есть отправная точка для приложения с базой данных, созданной из модели сущностей. Если нам необходимо обновить модель сущностей в будущем, мы можем выполнить действия, описанные во второй части, и просто обновить файл DataClasses.cs. Построение решения покажет вам все критические изменения и поможет найти то, что вам нужно обновить.
Еще предстоит проделать большую работу, чтобы сделать это приложение достойным рынка, но в течение следующих нескольких месяцев мы рассмотрим эти части, пока у нас не будет чего-то, что мы действительно представим.