Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Osnovy_razrabotki_prilozheny_besprovodnykh_ustr...docx
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
784.07 Кб
Скачать

Лабораторная работа №6. Учет затрат

Задание

Создать приложение "Учет затрат" для Windows Phone 7 с возможностью добавления новых доходов и расходов и подсчетом итоговой суммы.

Освоение

  • навигация между страницами

  • основные элементы управления и разметки (Grid, StackPanel, Canvas, TextBox, TextBlock, ListBox, Button)

  • события

  • контекст ввода

  • меню приложения

Описание

Создадим новый проект Silverlight for Windows Phone – Windows Phone Application.

Приложение будет состоять из двух окон:

  • главное окно со списком доходов/затрат

  • окно добавления новых доходов/затрат

Откроем файл разметки главной страницы MainPage.xaml. В самом верху страницы разметки изменим выводимое название приложения, например, на "УЧЁТ ЗАТРАТ". Заголовок страницы удалим или закомментируем с целью экономии места:

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">

<TextBlock x:Name="ApplicationTitle" Text="УЧЁТ ЗАТРАТ" Style="{StaticResource PhoneTextNormalStyle}"/>

<!--TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/-->

</StackPanel>

Внутри элемента ContentPanel поместим список доходов/затрат. Список будет иметь вид таблицы с 3 столбцами: название, актив/пассив (актив – доход, пассив – расход) и сумма. Итак, код элемента ContentPanel будет выглядеть следующим образом:

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" Canvas.ZIndex="0">

<Grid.RowDefinitions>

<RowDefinition Height="50" />

<RowDefinition />

</Grid.RowDefinitions>

<Grid.ColumnDefinitions>

<ColumnDefinition Width="300" />

<ColumnDefinition Width="50" />

<ColumnDefinition Width="100" />

</Grid.ColumnDefinitions>

<TextBlock Text="название" FontSize="28" Margin="0,0,5,0" TextAlignment="Center" Grid.Row="0" Grid.Column="0" />

<TextBlock Text="а|п" FontSize="28" Margin="0,0,5,0" TextAlignment="Center" Grid.Row="0" Grid.Column="1" />

<TextBlock Text="сумма" FontSize="28" Margin="0,0,5,0" TextAlignment="Center" Grid.Row="0" Grid.Column="2" />

<ListBox Name="lstElements" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3">

<ListBoxItem>

<StackPanel Orientation="Horizontal" Margin="0,10,0,10">

<TextBlock Text="Элемент списка" FontSize="28" Width="300" />

<TextBlock Text="А" FontSize="28" Width="50" TextAlignment="Center" />

<TextBlock Text="3000" FontSize="28" Width="100" TextAlignment="Right" />

</StackPanel>

</ListBoxItem>

</ListBox>

</Grid>

Внутри элемент Grid сначала помещаем объявление строк и столбцов, а затем и сами элементы управления. Внутри элементов управления с помощью атрибутов Grid.Row иGrid.Column задаются индексы, соответственно, строки и столбца.

В первой строке поместим заголовки столбцов, во второй – сам список. С помощью атрибута Grid.ColumnSpan можно объединять столбцы. Элементы списка объединим с помощью StackPanel с горизонтальной ориентацией.

В конце страницы раскомментируем фрагмент кода, отвечающий за меню приложения. Добавим еще одну кнопку. Объявим обработчики нажатия на кнопки меню и добавим значки. Значки можно найти в папке C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Icons (лучше всего брать из папки dark) или нарисовать самостоятельно. Добавим в проект папку "Images" и поместим в нее необходимые изображения. Для каждого из изображений в свойствах назначим полю Build Action значение Content (если этого не сделать, ApplicationBar не сможет найти изображения).

<!--Sample code showing usage of ApplicationBar-->

<phone:PhoneApplicationPage.ApplicationBar>

<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">

<shell:ApplicationBarIconButton IconUri="Images/appbar.check.rest.png" Text="Подсчет"

Click="ApplicationBarMenuCount_Click" />

<shell:ApplicationBarIconButton IconUri="Images/appbar.add.rest.png" Text="Добавить"

Click="ApplicationBarMenuAdd_Click" />

<shell:ApplicationBarIconButton IconUri="Images/appbar.cancel.rest.png" Text="Удалить"

Click="ApplicationBarMenuRemove_Click" />

<!--shell:ApplicationBar.MenuItems>

<shell:ApplicationBarMenuItem Text="MenuItem 1"/>

<shell:ApplicationBarMenuItem Text="MenuItem 2"/>

</shell:ApplicationBar.MenuItems-->

</shell:ApplicationBar>

</phone:PhoneApplicationPage.ApplicationBar>

Перейдем к написанию кода.

Поскольку работать с локальной базой и файлами мы пока не умеем, для сохранения данных будем использовать статический класс MyDatabase. Создадим его. Он будет содержать список элементов типа MyElement, который нам также необходимо создать:

public struct MyElement

{

public string Element;

public bool Active;

public float Money;

}

Кроме того статический класс будет содержать функцию инициализации списка (несколько элементов зададим заранее в этой функции):

public static class MyDatabase

{

public static List<MyElement> Values;

public static void Init()

{

Values = new List<MyElement>();

MyElement tmp;

tmp.Element = "зарплата";

tmp.Active = true;

tmp.Money = 15000f;

Values.Add(tmp);

tmp.Element = "донор крови";

tmp.Active = true;

tmp.Money = 2000f;

Values.Add(tmp);

tmp.Element = "ресторан";

tmp.Active = false;

tmp.Money = 3500f;

Values.Add(tmp);

}

}

Теперь откроем файл MainPage.xaml.cs. В самый верх для обеспечения перехода между страницами добавим директиву:

using System.Windows.Navigation;

В класс MainPage добавим функцию формирования элементов ListBox страницы из списка класса MyDatabase. Для этого будем последовательно создавать экземпляры класса TextBlock, задавать свойства и помещать их в экземпляры класса StackPanel, которые, в свою очередь, будем помещать в ListBoxItem, а те уже – в список.

private void DrawList()

{

lstElements.Items.Clear();

for (int i = 0; i < MyDatabase.Values.Count; i++)

{

ListBoxItem lstitNew = new ListBoxItem();

StackPanel spNew = new StackPanel();

TextBlock tbElem = new TextBlock();

TextBlock tbAP = new TextBlock();

TextBlock tbMoney = new TextBlock();

tbElem.Text = MyDatabase.Values[i].Element;

tbElem.FontSize = 28;

tbElem.Width = 300;

tbAP.Text = MyDatabase.Values[i].Active ? "А" : "П";

tbAP.FontSize = 28;

tbAP.Width = 50;

tbAP.TextAlignment = TextAlignment.Center;

tbMoney.Text = MyDatabase.Values[i].Money.ToString();

tbMoney.FontSize = 28;

tbMoney.Width = 100;

tbMoney.TextAlignment = TextAlignment.Right;

spNew.Orientation = System.Windows.Controls.Orientation.Horizontal;

spNew.Margin = new Thickness(0, 10, 0, 10);

spNew.Children.Add(tbElem);

spNew.Children.Add(tbAP);

spNew.Children.Add(tbMoney);

lstitNew.Content = spNew;

lstElements.Items.Add(lstitNew);

}

}

В конструкторе класса MainPage проинициализируем список и "нарисуем" его:

// Constructor

public MainPage()

{

InitializeComponent();

MyDatabase.Init();

DrawList();

}

Переход на главную страницу может быть осуществлен только в самом начале при загрузке приложения и при переходе со страницы добавления доходов/затрат. Таким образом, при переходе список может быть изменен. Поэтому нам следует перерисовывать его. Для этого переопределим стандартный метод OnNavigatedTo():

// Вызывается при переходе на текущую страницу

protected override void OnNavigatedTo(NavigationEventArgs e)

{

base.OnNavigatedTo(e);

if (null != MyDatabase.Values)

{

DrawList();

}

}

Теперь напишем обработчики нажатий на кнопки меню. При нажатии на кнопку "Подсчет" просто будем выводить в MessageBox-е сводку по доходам, расходам и общей сумме. При нажатии на кнопку "Добавить" просто будем осуществлять переход на страницу добавления доходов/расходов (PageAdd.xaml), которую создадим далее. При нажатии на кнопку "Удалить" будем удалять элемент с выделенных индексом из списка и перерисовывать его.

// Меню - Подсчет

private void ApplicationBarMenuCount_Click(object sender, EventArgs e)

{

float fActive = 0f;

float fPassive = 0f;

float fItog = 0f;

for (int i = 0; i < MyDatabase.Values.Count; i++)

{

if (MyDatabase.Values[i].Active)

{

fActive += MyDatabase.Values[i].Money;

}

else

{

fPassive += MyDatabase.Values[i].Money;

}

}

fItog = fActive - fPassive;

MessageBox.Show(

"Доходы: " + fActive.ToString() + "\n" +

"Расходы: " + fPassive.ToString() + "\n\n" +

"Итого: " + fItog.ToString()

);

}

// Меню - Добавить

private void ApplicationBarMenuAdd_Click(object sender, EventArgs e)

{

NavigationService.Navigate(new Uri("/PageAdd.xaml", UriKind.Relative));

}

// Меню - Удалить

private void ApplicationBarMenuRemove_Click(object sender, EventArgs e)

{

int nIndex = lstElements.SelectedIndex;

if (-1 != nIndex)

{

MyDatabase.Values.RemoveAt(nIndex);

DrawList();

}

else

{

MessageBox.Show("Элемент не выбран.");

}

}

Теперь добавим в проект приложения новую страницу – Windows Phone Portrait Page. Назовем ее PageAdd. В файле PageAdd.xaml определим разметку страницы. Она будет включать два текстовых поля (для названия дохода/расхода и суммы), один CheckBox (для определения расход это или доход) и две кнопки – "Принять" и "Отмена". Также не забудем про элементы TextBlock с пояснительными подписями к текстовым полям.

<!--TitlePanel contains the name of the application and page title-->

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">

<TextBlock x:Name="ApplicationTitle" Text="БАЗА ПАРОЛЕЙ" Style="{StaticResource PhoneTextNormalStyle}"/>

<!--TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/-->

</StackPanel>

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

<StackPanel Margin="5,5,5,5">

<Grid ShowGridLines="False" Margin="0,20,0,0">

<Grid.RowDefinitions>

<RowDefinition />

<RowDefinition />

<RowDefinition />

</Grid.RowDefinitions>

<Grid.ColumnDefinitions>

<ColumnDefinition Width="120" />

<ColumnDefinition Width="320" />

</Grid.ColumnDefinitions>

<TextBlock Name="lblElem" Text="Расход:" Grid.Column="0" Grid.Row="0"

VerticalAlignment="Center" FontSize="24" />

<TextBlock Text="Сумма:" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center" FontSize="24" />

<TextBox Name="txtElem" Text="Элемент" Grid.Column="1" Grid.Row="0" />

<TextBox Name="txtMoney" Text="0" InputScope="Number" Grid.Column="1" Grid.Row="1" />

<CheckBox Name="checkActive" Content="Прибыль" Grid.Column="1" Grid.Row="2"

Click="checkActive_Click" />

</Grid>

<StackPanel Orientation="Horizontal">

<Button Name="btnApply" Height="90" Width="220" Grid.Column="0" Grid.Row="0" Content="Принять"

Click="btnApply_Click" />

<Button Name="btnCancel" Height="90" Width="220" Grid.Column="1" Grid.Row="0" Content="Отмена"

Click="btnCancel_Click" />

</StackPanel>

</StackPanel>

</Grid>

</Grid>

Перейдем к коду страницы PageAdd.xaml.cs.

Точно так же в самый верх добавим директиву:

using System.Windows.Navigation;

При переходе на данную страницу будем очищать текстовые поля и снимать галочку с CheckBox-а:

protected override void OnNavigatedTo(NavigationEventArgs e)

{

base.OnNavigatedTo(e);

txtElem.Text = "";

txtMoney.Text = "";

checkActive.IsChecked = false;

txtElem.Focus();

}

При нажатии на CheckBox просто будем менять текст в текстовом блоке lblElem для удобства пользователя:

private void checkActive_Click(object sender, RoutedEventArgs e)

{

if (checkActive.IsChecked.Value)

lblElem.Text = "Доход:";

else

lblElem.Text = "Расход:";

}

При нажатии на кнопку "Отмена" будем переходить на предыдущую главную страницу, ничего не изменяя. При нажатии на кнопку "Принять" будем добавлять новый элемент в список MyDatabase.Values:

private void btnCancel_Click(object sender, RoutedEventArgs e)

{

MessageBoxResult result = MessageBox.Show("Изменения будут потеряны.

Продолжить?", "Отмена", MessageBoxButton.OKCancel);

if (result == MessageBoxResult.OK)

{

NavigationService.GoBack();

}

}

private void btnApply_Click(object sender, RoutedEventArgs e)

{

if (txtElem.Text.Trim().Length > 0)

{

if (txtMoney.Text.Trim().Length > 0)

{

MyElement tmp;

tmp.Element = txtElem.Text;

tmp.Active = checkActive.IsChecked.Value;

tmp.Money = float.Parse(txtMoney.Text);

MyDatabase.Values.Add(tmp);

NavigationService.GoBack();

}

else

{

MessageBox.Show("Поле суммы не может быть пустым.");

txtMoney.Focus();

}

}

else

{

if(checkActive.IsChecked.Value)

MessageBox.Show("Поле дохода не может быть пустым.");

else

MessageBox.Show("Поле расхода не может быть пустым.");

txtElem.Focus();

}

}

Теперь можно скомпилировать приложение, запустить на эмуляторе или телефоне и проверить его функциональность.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]