maran program engineering (830029), страница 25
Текст из файла (страница 25)
Простейший примерРассмотрим работу с компонентами интерфейса на примере команднойкнопки Button, которая должна всегда быть расположена в правом нижнем углуокна. Занесем ее в нужную клетку и обратимся к ее свойствам. Первое отличиеот Windows Forms — компоненты интерфейса не имеют имен по умолчанию.Если мы в своих программах на них ссылаться не будем, то это и не важно. Дадим нашей кнопке имя Close1.
Видимый на экране на кнопке текст является теперь значением свойства Content (у нас Close). В окне поиска свойств введемalign…, и откроется возможность определения выравнивания самой кнопки итекста в нем. Поставим выравнивание кнопки вниз и направо. Выравниваниетекста менять не будем (останется в центре кнопки). Сбросим поиск выравнивания и наберем для поиска Margin, это свойство показывает расстояние дограниц «мини-клетки», в которой находится Button. Так как мы задали выравнивание вниз и направо, то важны только значения расстояний до этих границ,зададим их равными нулю.
Осталась лишь реализация кнопки. Переключаемокно ее свойств на события, выберем событие Click, делаем на нем двойнойщелчок и в заготовку функции пишем знакомое Close(); запустим приложениеи, изменяя размер окна, убедимся, что наша кнопка всегда будет в нижнем правом углу.Поставим на наше окно поле TextBox и расположим его в верхнем левомуглу, но так, чтобы он занимал 3 «мини-клетки» по горизонтали. Дадим емуимя txt1, видимый на экране текст задается, как и раньше, в свойстве Text.
Мыуже знаем, как обеспечить его расположение. Дополнительно: свойствоGrid.Column определяет номер столбца расположения его левой границы;Grid.Row — номер строки расположения его верхней границы;Grid.ColumnSpan — сколько столбцов оно занимает; Grid.RowSpan — сколькострок занимает. Значения всех свойств можно менять визуально на самом окне,в тексте на XAML или в окне свойств. Результат от этого не зависит.Нанесем на окно:• для вывода результатов компонент Label, имя Out1, видимый на экранетекст задается в его свойстве Content;• для запуска обработки массива-строки командную кнопку, имя Row1,текст на ней Row;• для ввода массива-столбца еще один textBox, имя txt2, в кнопку выборасвойства AcceptsReturn ставим галочку;• для запуска обработки массива-столбца создадим кнопку, имя Col1, текстна ней Column.151Кроме описанного выше, имеется еще один способ реализации командной кнопки.
Найдем в XAML ее описание, поставим курсор мыши после любогосвойства, нажмем на пробел и из выпадающего списка свойств и событий выбираем Click и ставим ему в соответствие новую функцию. Внешний вид формы представлен на рис. 5.19.Рис. 5.19Текст на XAML:Window x:Class="WpfSimple1.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="400" Width="525" FontSize="18"><Grid><Grid.RowDefinitions><RowDefinition/>//определение строк, интервалы равные<RowDefinition/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions>//определние столбцов, интервалы разные<ColumnDefinition Width="126*"/><ColumnDefinition Width="132*"/><ColumnDefinition Width="130*"/><ColumnDefinition Width="129*"/></Grid.ColumnDefinitions><Button x:Name="close1" Content="Close" Grid.Column="3" HorizontalAlignment="Right" Height="42" Grid.Row="2" VerticalAlignment="Top"Width="92" Margin="0,81,0,0" Click="close1_Click" HorizontalContentAlignment="Center" RenderTransformOrigin="-1.236,-2.725"/> //свойстваButton152<TextBox x:Name="txt1" Grid.ColumnSpan="3" HorizontalAlignment="Left"Height="53" Margin="0" TextWrapping="Wrap" VerticalAlignment="Top" Width="321"/> //свойства TextBox<Label x:Name="Out1" Content="Answer" Grid.Column="2" HorizontalAlignment="Left" Height="49" Margin="10,29,0,0" Grid.Row="1" VerticalAlignment="Top" Width="110"/>//свойства Label<Button x:Name="Row1" Content="Row" Click="Row1_Click"Grid.Column="3" HorizontalAlignment="Left" Height="52" Margin="25,36,0,0" VerticalAlignment="Top" Width="94"/><TextBox x:Name="txt2" HorizontalAlignment="Left" Height="179" Margin="40,31,0,0" Grid.Row="1" TextWrapping="Wrap" VerticalAlignment="Top" Width="76" Grid.RowSpan="2" AcceptsReturn="True"/><Button x:Name="Col1" Content="Column" Grid.Column="1"Click="Col1_Click" HorizontalAlignment="Left" Height="48" Margin="37,22,0,0" Grid.Row="1" VerticalAlignment="Top" Width="71" RenderTransformOrigin="-3.455,0.049"/></Grid></Window>Реализация двух командных кнопок:private void Row1_Click(object sender, RoutedEventArgs e){ // Обработка масссива-строки, описание приведено выше.string s;string[] dan;int[] mas;s = txt1.Text;dan = s.Split(';');dan = dan.Where(p => p != "").ToArray();mas = new Int32[dan.Length];for (int i = 0; i < mas.Length; i++)mas[i] = Convert.ToInt32(dan[i]);int kol = mas.Where(p => p > 0).Count();153Out1.Content = "" + kol;}private void Col1_Click(object sender, RoutedEventArgs e){ //Описание массива-столбцаList<string> lst1 = new List<string>();int m;string y;double[] arr;double summa;for (int i=0;;i++){y = txt2.GetLineText(i);if(y=="\r\n")continue;// Символы перевода строки входят в у,//если строка состоит только из них, то она пуста.if (y == "") break;m=y.IndexOf("\r\n");if(m>-1) y=y.Substring(0,y.Length-2);//символы "\r\n" должны быть удалены.lst1.Add(y);if (m < 0) break;}arr = new double[lst1.Count];for (int i = 0; i < arr.Length; i++)arr[i] = Double.Parse(lst1[i]);summa = arr.Where(p => p > 1.5).Sum();Out1.Content = summa.ToString("F1");}5.10.2.
Работа с двумерным форматизированным массивомДля представления двумерного массива в окне используем знакомый намкомпонент DataGrid, дадим ему имя dg1. Для внутреннего представления используем класс DataTable с именем tab1. Необходимо добавитьusing System.Data;Для показа возможностей WPF изменим внешний вид формы, рис. 5.20.Оставим читателю поиск ответа на вопросы: «Какими свойствами можно этосделать? Какие еще возможности для изменения внешнего вида имеются?»154Рис.
5.20Реализация обработки похожа на приведенную выше для Windows Forms,но имеются и отличия.public partial class MainWindow : Window{DataSet ds;DataTable tab1;void InitGrid(int n, int m){tab1 = new DataTable();DataColumn x1 = tab1.Columns.Add("Number",typeof(Int32));DataColumn x2;for (int i = 0; i < n; i++){x2 = tab1.Columns.Add("Col " + i, typeof(Double));x2.DefaultValue = 0;}DataRow dr;for (int i = 0; i < m; i++){dr = tab1.NewRow();tab1.Rows.Add(dr);tab1.Rows[i][0] = (Int32)(i + 1);}x1.ReadOnly = true;155ds.Tables.Add(tab1);//Добавим созданную таблицу в DataSet}public MainWindow(){InitializeComponent();ds = new DataSet();InitGrid(3, 4);dg1.ItemsSource = ds.Tables[0].DefaultView;// Связываем tab1 и dg1.}private void Comp1_Click(object sender, RoutedEventArgs e){ // Вычислениеdouble s = 0;foreach (DataRow x in tab1.Rows)for (int j = 1; j < tab1.Columns.Count; j++)s += Convert.ToDouble(x[j]);Answer1.Content = s.ToString("F1");}private void Chng1_Click(object sender, RoutedEventArgs e){ // Изменение данныхdouble x;for(int i=0;i<tab1.Rows.Count;i++)for(int j=1;j<tab1.Columns.Count;j++){x = (double)tab1.Rows[i][j];x *= 1.5;tab1.Rows[i][j] = x;}}}5.10.3.
Работа со спискомСоздаем список с элементами следующей{get;set;} обязательно!):class Person{public string name{get;set;}public int age {get;set;}public bool member {get;set;}156}структуры(Наличиена окно занесем знакомый нам компонент dataGridView, дадим ему имя dg1 ивыравниваем. Дополнения класса MainWindow и его конструктора:public partial class MainWindow : Window{List<Person>lst1;Person temp;public MainWindow(){InitializeComponent();lst1=new List<Person>();dg1.ItemsSource = lst1;} ...Внешний вид окна представлен на рис. 5.21. В WPF меню может находиться в любом месте окна, для разнообразия пусть оно будет внизу.Рис. 5.21Для создания меню перенесем на окно компонент Menu и расположим еговнизу окна, его область на окне должна быть достаточна для размещения всехпунктов горизонтального меню.
Для создания пунктов горизонтального менювыделим его на экране, выделим свойство Items и диалоговое окно созданияменю. Определим тип пунктов меню MenuItems («классическое» меню, имеются и другие варианты) и создаем горизонтальное меню. Тексты его пунктов пишем в свойство Header. Для создания пунктов выпадающего меню выделимнужный пункт горизонтального и повторим описанное выше и для него. Приведем описание меню на XAML:157<Menu Grid.ColumnSpan="3" HorizontalAlignment="Right"Height="39" Margin="0" Grid.Row="3" VerticalAlignment="Bottom"Width="497" FontSize="20"> //начинается описание меню<MenuItem x:Name="File1" Header="Файл"><MenuItem x:Name="Exit" Header="Выход" Click="Exit_Click"/>//имя, текст на окне, функция реализации</MenuItem><MenuItem x:Name="ListOper" Header="Операции со списком"><MenuItem x:Name="Insert1" Header="Добавление"Click="Insert1_Click" /><MenuItem x:Name="Change1" Header="Изменение"Click="Change1_Click" /><MenuItem x:Name="Computing1" Header="Вычисление"Click="Cоmputing1_Click" /></MenuItem></Menu>По мнению автора, после приобретения первых навыков работы с менюпроще его создать именно здесь.
Правда, имеются широкие возможности выбора его внешнего вида, желаем читателю самому поэкспериментировать. Реализации пунктов меню:Программное добавление новых элементов (в нашем случае их берут сэкрана, но они могут быть получены и в программе):private void Insert1_Click(object sender, RoutedEventArgs e){temp = new Person();dg1.ItemsSource = null;temp.name = name1.Text;temp.age = Convert.ToInt32(age1.Text);temp.member =(bool) member1.IsChecked;lst1.Add(temp);dg1.ItemsSource = lst1;name1.Clear();age1.Clear();}Обратите внимание, что при изменении списка программой надо отключить представление на окне, а после внесения изменений восстановить.
Иначеизменения не будут показаны на экране.Изменение списка программно, изменен будет выделенный на экранеэлемент:private void Change1_Click(object sender, RoutedEventArgs e){temp = (Person)dg1.SelectedItem;158dg1.ItemsSource = null;temp.age += 3;dg1.ItemsSource = lst1;}Выполнение вычислений; можно использовать внутреннее или внешнеепредставление списка:private void Computing1_Click(object sender, RoutedEventArgs e){// цикл по dataGriddouble sr = 0;for (int i = 0; i < dg1.Items.Count-1; i++)sr += ((Person)dg1.Items[i]).age;answer.Content =(sr/(dg1.Items.Count-1)).ToString("F2");// вычисление по спискуsr = lst1.Select(p => p.age).Average();}Оставим на конец самое простое средство работы со списком: можем ввести новый элемент прямо в DataGrid и фиксировать его нажатием Enter.