Многокомпонентные элементы управления

52

Целый ряд элементов управления на платформах WPF и Silverlight обладает способностью содержать список элементов типа ListBox или ComboBox. Подобно подлинным элементам управления содержимым, элементы управления типа ListBox могут содержать простую порцию строковых данных или более сложные элементы, составляющие целый список. В самом общем смысле такой список специальных элементов можно считать "содержимым", а более конкретно — в подобных элементах управления применяется модель содержимого многокомпонентных элементов управления.

В качестве примера создайте не совсем обычный элемент управления типа ListBox в совершенно новом проекте приложения WPF — FancyListBox. С этой целью добавьте элемент управления типа ListBox на монтажном столе нового проекта и присвойте ему имя customListBox (специальное списковое окно) на панели Properties.

Затем добавьте на монтажном столе элемент управления типа Label, присвоив ему имя currentSelection (выбранное в текущий момент) и расположив его чуть ниже элемента управления типа ListBox. Вновь введенный элемент управления типа Label будет служить для отображения конкретного значения выбранного в настоящий момент элемента, и для этой цели он будет настроен чуть позже.

Добавление объектов типа ListBoxItems

Для того чтобы добавить элементы в список, представленный элементом управления типа ListBox, можно, в частности, щелкнуть правой кнопкой мыши на этом элементе управления непосредственно на монтажном столе и выбрать команду Add ListBoxItem (Добавить элемент спискового окна) из всплывающего контекстного меню. (Если же выбрать элемент управления типа ComboBoxItem, то в контекстном меню соответственно появится команда Add ComboBoxItem.)

Подобным способом к выбранному элементу управления добавляется новый объект типа ListBoxItem, содержащий простой текст, который можно в далбнейшем отформатировать. Итак, воспользуйтесь данным способом, чтобы добавить в список, представленный элементов управления ListBox, единственный элемент в виде объекта типа ListBoxItem:

Добавление новых элементов в список

Выделите и растяните мышью новый объет типа ListBoxItem, чтобы заполнить им элемент управления ListBox приблизительно на половину высоты последнего, как показано на рисунке:

Изменение размеров объекта типа ListBoxItem

Убедитесь сначала в том, что объект типа ListBoxItem выбран в настоящий момент на панели Objects and Timeline, а затем добавьте к этому объекту элемент управления типа StackPanel таким же образом, как делали это в предыдущем примере проекта с необычной кнопкой. Выберите элемент управления типа StackPanel на панели Objects and Timeline, найдите свойство Orientation на панели Properties, введя, например, его имя в поле поиска Search, и установите в этом свойстве значение Horizontal.

После этого вам придется изменить размеры нового элемента управления типа StackPanel, чтобы благополучно вписать его в объект типа ListBoxItem, который его содержит. Поэтому уделите немного времени упорядочению этих объектов на монтажном столе по своему усмотрению.

А далее следует самое интересное. Выберите сначала элемент управления типа StackPanel на панели Objects and Timeline, а затем добавьте к нему объекты типа Ellipse и Label стандартными для Expression Blend способами, используя, в частности, панель Tools, библиотеку ресурсов и т.д. После этого иерархическое представление рассматриваемого здесь элемента управления на панели Objects and Timeline должно выглядеть так, как показано на рисунке:

Иерархическое представление объекта типа ListBoxItem

Измените размеры новых объектов, чтобы вписать их в элемент управления с составным содержимым. Выберите на панели Properties красный цвет заполнения для свойства Fill объекта типа Ellipse и установите текстовое значение Red (Красный) в свойстве Content объекта типа Label.

Выберите объект типа ListBoxItem на панели Objects and Timeline, щелкните на нем правой кнопкой мыши и выберите команду Сору из всплывающего контекстного меню. После этого выберите элемент управления типа ListBox на панели Objects and Timeline, щелкните на нем правой кнопкой мыши и выберите команду Paste из всплывающего контекстного меню. Повторите эту же процедуру еще три раза, чтобы в конечном итоге заполнить элемент управления типа ListBox четырьмя объектами типа ListBoxItem.

Затем воспользуйтесь панелью Properties, чтобы подобрать особые цвета заполнения для свойств Fill новых объектов типа Ellipse и установить соответствующие им текстовые значения в свойствах Content новых объектов типа Label. В качестве примера на рисунке приведен окончательный вид компоновки элемента управления типа ListBox:

Окончательный вид элемента управления ListBox

Если вы перейдете к редактору XAML, то обнаружите, что элемент управления типа ListBox действительно содержит четыре объекта типа ListBoxItem. Но вместо простого текста они теперь содержат составные элементы пользовательского интерфейса, как показано ниже:

<ListBox x:Name="customListBox" Margin="270,80,172,184.667">
			<ListBoxItem Height="43.276" VerticalAlignment="Center">
				<StackPanel Height="42" Width="100" Orientation="Horizontal">
					<Ellipse Margin="0,0.028,0,2.971" Width="38.667" StrokeThickness="0">
						<Ellipse.Fill>
							<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
								<GradientStop Color="#FFEB6666" Offset="0"/>
								<GradientStop Color="#FFF31515" Offset="1"/>
							</LinearGradientBrush>
						</Ellipse.Fill>
					</Ellipse>
					<Label Content="Red" VerticalContentAlignment="Center" Width="56.03" Padding="15,5,5,5"/>
				</StackPanel>
			</ListBoxItem>
            ...

Независимо от содержимого объектов типа ListBoxItem, будь то простой текст или блочная панель типа StackPanel с несколькими элементами, выявить элемент, выбранный из списка, можно с помощью свойства SelectedIndex (Индекс выбранного), имеющегося у элемента управления типа ListBox. Из этого свойства возвращается отсчитываемое от нуля значение, где 0 обозначает первый элемент в списке, 1 — второй элемент и т.д.

Итак, выберите элемент управления типа ListBox на панели Objects and Timeline и щелкните на кнопке Events панели Properties, чтобы организовать обработку события SelectionChanged, наступающего при выборе нового элемента из списка, представленного элементом управления типа ListBox, как показано на рис. (Напомним, что для автоматического формирования обработчика событий в файле исходного кода текущего проекта достаточно дважды щелкнуть на текстовом поле рядом с меткой обрабатываемого события на панели Properties.):

Обработка события SelectionChanged

Ниже показано, каким образом в коде обработчика событий реализуется отображение порядкового номера элемента, выбранного в текущий момент из списка, в поле элемента управления сurrentSelection типа Label:

private void customListBox_SelectionChanged(object sender, 
        System.Windows.Controls.SelectionChangedEventArgs e)
		{
			this.currentSelection.Content = 
				string.Format("Вы выбрали цвет под номером {0}",this.customListBox.SelectedIndex + 1);
		}

Запустите свое приложение на выполнение и обратите внимание на возможность выбрать как и предполагалось, любой специальный элемент из списка:

Списковое окно в действии

Применение свойства Tag

Итак, вы научились обнаруживать порядковый номер элемента, выбранного в текущий момент из списка. Но было бы намного интереснее обнаруживать и цвет (красный, зеленый и т.д.), связанный с выбранным элементом. И этого, как оказывается, вполне возможно добиться с помощью шаблона данных. Однако в качестве простой альтернативы можно воспользоваться свойством Tag.

Выберите на панели Objects and Timeline объект типа ListBoxItem, содержащий красный эллипс. После этого найдите на панели Properties свойство Tag (Признак) — оно находится среди дополнительных свойств, выбираемых из области Common Properties. Установите в этом свойстве значение "красный". Повторите эту же процедуру для остальных объектов типа ListBoxItem, настроив их свойства Tag на соответствующий цвет эллипса.

Теперь обновите имеющийся обработчик событий типа SelectionChanged, чтобы извлекать значение свойства Tag выбранного в настоящий момента объекта типа ListBoxItem и присваивать это значение свойству Content элемента управления типа Label как показано ниже:

private void customListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
	string colorSelected = ((ListBoxItem)this.customListBox.SelectedItem).Tag.ToString();
	this.currentSelection.Content = string.Format("Вы выбрали {0} цвет",colorSelected);
}

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

Пройди тесты
Лучший чат для C# программистов