Как стать автором
Обновить

Список сообщений в стиле Message Hub

Время на прочтение3 мин
Количество просмотров8.8K
Если вы уже разрабатывали приложения под Windows Phone 7, то возможно уже заметили отсутствие некоторых элементов управления, таких как Hub Tile, сгруппированный список или список сообщений. Некоторые из них можно найти в библиотеке Silverlight Toolkit for Windows Phone. Но что делать, когда нам нужно создать приложение, похожее на стандартный Message Hub? Основная проблема заключается в том, что в стандартном LisBox'е элементы размещаются cверху вниз, в то время как в хабе сообщений — наоборот.



Хочу продемонстрировать одно из решений данной задачи. Нам понадобится лишь стандартный элемент управления ListBox, библиотека System.Windows.Interaction из Blend SDK и некоторые знания в области трансформации визуальных компонентов.

Итак. Как я уже говорил, стандартный ListBox размещает свои элементы в VirtualizingStackPanel в направлении сверху вниз. Написание своего VirtualizingStackPanel, который будет размещать элементы снизу вверх, может занять очень много времени. К тому же стандартный VirtualizingStackPanel уже содержит логику виртуализации, которая решает проблему потребления огромных объёмов памяти. Всё что нам нужно, это перевернуть ListBox вверх ногами, так, чтоб новые элементы размещались снизу. Для этого используем ScaleTransform:

<ListBox>
	<ListBox.RenderTransform>
		<ScaleTransform ScaleX="1" ScaleY="-1">
	</ListBox.RenderTransform>
</ListBox>

Теперь наш ListBox перевёрнут, но уехал вверх. Для того, чтобы вернуть его на место, нужно указать центр трансформации. В нашем случае это середина по вертикали, т.е.:

_scaleTransform.CenterY = ListBox.ActualHeight / 2;

Как вы могли заметить, элементы нашего ListBox тоже перевёрнуты. Для того, чтобы вернуть их в нормальное положение, воспользуемся тем же методом, который мы использовали для всего списка.

Поклонники MVVM могут покривиться лишнему коду в .xaml.cs файлах. Всю дополнительную логику я обычно пишу в Behavior'ах из библиотеки System.Windows.Interaction. Для этого создадим класс MirrorBehavior c кодом:

public class MirrorBehavior : Behavior<Control>
{
	private readonly ScaleTransform _transform = new ScaleTransform();

	public MirrorBehavior()
	{
		_transform.ScaleX = 1;
		_transform.ScaleY = -1;
	}

	protected override void OnAttached()
	{
		UpdateCenter();

		AssociatedObject.SizeChanged += AssociatedObject_SizeChanged;

		AssociatedObject.RenderTransform = _transform;
	}

	protected override void OnDetaching()
	{
		AssociatedObject.RenderTransform = null;

		AssociatedObject.SizeChanged -= AssociatedObject_SizeChanged;

		ResetCenter();
	}

	private void AssociatedObject_SizeChanged(object sender, SizeChangedEventArgs e)
	{
		UpdateCenter();
	}

	private void UpdateCenter()
	{
		_transform.CenterY = AssociatedObject.ActualHeight / 2;
	}

	private void ResetCenter()
	{
		_transform.CenterY = 0;
	}
}

Осталось только применить его к нашим элементам управления:

<ListBox ItemsSource="{Binding Messages}">

	<i:Interaction.Behaviors>
		<Interactivity:MirrorBehavior />
	</i:Interaction.Behaviors>

	<ListBox.ItemTemplate>
		<DataTemplate>
			<ContentControl HorizontalContentAlignment="Stretch"
							VerticalContentAlignment="Stretch"
							ContentTemplate="{StaticResource MessageTemplate}"
							Content="{Binding}">

				<i:Interaction.Behaviors>
					<Interactivity:MirrorBehavior />
				</i:Interaction.Behaviors>

			</ContentControl>
		</DataTemplate>
	</ListBox.ItemTemplate>
</ListBox>

Данное решение хорошо тем, что использует стандартные стили и встроенную виртуализацию.
Теги:
Хабы:
Всего голосов 34: ↑30 и ↓4+26
Комментарии48

Публикации

Истории

Работа

Ближайшие события

19 сентября
CDI Conf 2024
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн