В первой и второй частях мы использовали 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. Построение решения покажет вам все критические изменения и поможет найти то, что вам нужно обновить.
Еще предстоит проделать большую работу, чтобы сделать это приложение достойным рынка, но в течение следующих нескольких месяцев мы рассмотрим эти части, пока у нас не будет чего-то, что мы действительно представим.