вторник, 23 сентября 2008 г.

Некоторые аспекты databinding, показ datatable в listbox

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



Во-первых необходимо связать содержимое, загружаемое из файла в listbox:

добавляем в код XAML:

< itemtemplate="{StaticResource nodsTemplate}" itemssource="{Binding}" name="listBoxNods" margin="0,30,0,0">


ItemsSource="{Binding}" означает, что источник данных, показываемых в этом листбоксе забинден к нему, т.е. они соединены между собой постоянной связью, и изменения в одном могут(если это не запрещено специально) сразу отображаться в другом.

ItemTemplate="{StaticResource nodsTemplate}" - это темплейт, с помощью которого мы рассказываем listbox'у как и что мы хотим отображать конкретно:



< key="nodsTemplate"> < name="grid">
< name="nodsPanel0" orientation="Horizontal">
< name="nodsPanel1" width="100" horizontalalignment="Left">
< text="{Binding Path = x}">
< name="nodsPanel2" width="50" horizontalalignment="Right">
< text="{Binding Path = y}">

как все происходит - listbox разбивается на StackPanelи первого вида(nodsPanel0), которые будут отображаться одна под другой, далее, каждая из этих стак-панелей разбивается еще на 2, горизонтально(за это отвечает атрибут Orientation), и в каждой из этих стак-панелей уже запихиваем те элементы которые нам нужны, в данном случае - TextBox и TextBlock, к которым привязываем конкретные данные, которые будем доставать из источника. Собствено в чем отличие текстбокса и текстблока - в том, что текстбокс изменяем, мы можем изменить в нем наши данные, и если DataTable к которой мы привязаны позволяет это - то данные от этого изменятся и в ней. Текстблок же - это просто статический текст. Т.к. стакпанели будут по умолчанию прилегать в плотную друг к другу, и занимать столько места, какова длинна данных, записаных в них, то имеет смысл для наведения красоты и для более удобного чтения данных установить фиксированную длинну через атрибут Width.в этом темплейте можно сделать еще очень много чего, но это уже не относится к теме данной статьи :) переходим в код C#.

Теперь нам необходимо указать, собственно какие данные мы забиндим к listbox:

DataTable _nods = new DataTable();

****

_nods.Columns[0].ColumnName = "x";
_nods.Columns[0].ReadOnly = false;
DataColumn tc1 = new DataColumn("y", typeof(double));
_nods.Columns.Add(tc1);
_nods.Columns[1].ReadOnly = true;

Binding bind = new Binding();
this.listBoxNods.DataContext = _nods;
this.listBoxNods.SetBinding(ItemsControl.ItemsSourceProperty, bind);

Сначала мы создаем и заполняем(это необязательно :) ) DataTable, и назначаем названия Columns. Необходимо, чтобы названия в Text="{Binding Path = x}" совпадали с названиями колонок таблицы, далее выставляем значения атрибута ReadOnly - если мы хотим чтобы данные в колонке не менялись из-за внешних воздействий(либо, например, чтобы запретить определенному кругу пользователей изменять какие-либо данные)

теперь, собственно, создаем биндинг и назначаем для листбокса его датаконтекст, и применяем биндинг. Вот и все :)


Комментариев нет: