Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
 WPF: Шпаргалка для создания панели  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19953
Написал себе (и другим) шпаргалку, чтобы не забывать особенности работы с компоновкой с помощью панели. А то делаешь панели не так уж часто, и мелкие нюансы забываются.

public class MyPanel : Panel
{
	protected override Size MeasureOverride(Size availableSize)
	{
		// availableSize - содержит доступные размеры, предоставляемые контейнером.
		// Может быть бесконечность по любому или обоим измерениям, если панель находится в StackPanel, ScrollViewer и т.п.

		var size = new Size(100, 200);
		foreach (UIElement child in InternalChildren)
		{
			var elementSize = size;
			child.Measure(elementSize);
			var desiredSize = child.DesiredSize;
		}

		// В elementSize передаем максимальные размеры, которые может предоставить элементу панель, исходя из логики панели и availableSize.
		// Можно передавать бесконечные размеры, в частности availableSize.
		// Панель может и не использовать результат измерения своих элементов, но вызов child.Measure обязателен.
		// Каждый элемент формирует в child.DesiredSize минимальные требования по своим размерам, но не более elementSize (Margin будут учтены автоматически)
		// Элемент не может вернуть бесконечные размеры.

		return new Size(100, 200); ;

		// Необходимо вернуть минимальные требования по размерам панели, исходя из логики панели и полученных минимальных размеров элементов и не более availableSize.
		// Нельзя возвращать бесконечные размеры.
		// Нельзя возвращать availableSize, так как availableSize может иметь бесконечные размеры.
		// Не стоит возвращать размеры меньше минимально необходимых, так как в итоге именно эти размеры впоследствии могут быть предоставлены контейнером.
		// Не стоит возвращать размеры больше минимально необходимых, это просто нарушает смысл происходящего

	}

	protected override Size ArrangeOverride(Size finalSize)
	{
		var size = new Size(100, 200);
		foreach (UIElement child in InternalChildren)
		{
			var elementRect = new Rect(new Point(0, 0), size);
			child.Arrange(elementRect);
		}

		// Вызов child.Arrange обязателен, без него элементы не будут отрендерены.
		// В elementRect передаем финальное расположение и размер области, предоставленной для элемента, согласно логике панели, finalSize и child.DesiredSize.
		// Если у элемента есть Margin, система сама их учтет, дополнительно уменьшив предоставленную элементу область.
		// Если элемент меньше отведенной области, он будет располагаться в ней согласно Horizontal- и VerticalAlignment.
		// Если элемент больше отведенной области, он будет рендериться в полный размер, но выходящая за пределы elementRect часть видна не будет.
		// Можно указать область, выходящую за пределы области самой панели, видимость за границей панели будет определяться ClipToBounds самой панели.
		// Нельзя указать бесконечный размер.
		// После вызова child.Arrange можно прочитать отрендеренный реальный размер элемента из ActualHeight и ActualWidth

		return size;

		// Как правило, возвращается finalSize
		// Можно вернуть размер меньше finalSize, тогда панель будет позиционироваться в контейнере согласно своим Horizontal- и VerticalAlignment.
		// Можно вернуть размер больше finalSize (в том числе и бесконечный размер), но выходящая за пределы finalSize часть видна не будет
	}
}



Гляньте, может у кого дополнения есть, или я где-то не очень прав.
В частности по поводу обрезания выходящих за границы частей (на что-то влияет ClipToBounds, на что-то нет).

ЗЫ: В учебниках везде написано про измерения, что элемент возвращает желаемый размер. Но ведь это не совсем правильный термин, на мой взгляд, я употребляю слово "минимальный". Например тот же <Border /> (без настроек) затребует себе Size(0,0).
11 фев 19, 02:00    [21805978]     Ответить | Цитировать Сообщить модератору
 Re: WPF: Шпаргалка для создания панели  [new]
Roman Mejtes
Member

Откуда: г. Пермь
Сообщений: 3167
Shocker.Pro,

не знаю, чем вам термин желаемый размер не нравится. Так как это объект класса, с точки зрения объекта, этот как раз желаемый размер объекта, который зависит от его состояния . То есть размер который требуется элементу, для того, чтоб отобразиться в наилучшем виде (в идеале).

А так шпаргалка отличная, я правда это и так всё помню
11 фев 19, 10:58    [21806156]     Ответить | Цитировать Сообщить модератору
 Re: WPF: Шпаргалка для создания панели  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19953
Roman Mejtes
не знаю, чем вам термин желаемый размер не нравится. Так как это объект класса, с точки зрения объекта, этот как раз желаемый размер объекта, который зависит от его состояния .
Я трактую так: если у элемента стоит HorizontalAlignment=Stretch, то его желаемая ширина - занять всё доступное пространство. Но затребует он именно минимальное. То есть <Border BorderThickness="1" HorizontalAlignment="Stretch" /> затребует ширину в 2 дипа, даже если ему передают бесконечность в распоряжение.


Roman Mejtes
я правда это и так всё помню
- Доктор, у меня это. Я всё забываю!
- А я всё помню! Вы у меня уже были.
(с) Картинка с другого сайта.

С нюансами по обрезанию пришлось поэкспериментировать. Как-то делал панель, никак не мог понять, почему элементы подрезаются, тыкал везде ClipToBounds - не помогало. То, что надо резать желаемый размер по availableSize тоже наверняка не знал, посмотрел, как штатные контролы поступают.

+
Roman Mejtes
чем вам
Может в этом году, может в следующем... хочу проехать на машине от Питера до Владика. Проезжая через Пермь, отловлю тебя там, затащу в ресторан и заставлю выпить на брудершафт, чтобы уж наконец ты перестал мне вы-кать Картинка с другого сайта.Картинка с другого сайта.
11 фев 19, 12:22    [21806249]     Ответить | Цитировать Сообщить модератору
 Re: WPF: Шпаргалка для создания панели  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19953
Roman Mejtes,

Подскажи, InternalChildren заведомо неизменен между MeasureOverride и ArrangeOverride?

Смысл вопроса в следующем: так как зачастую основной расчет компоновки происходит уже на этапе измерения, логично было бы уже составить карту, которую просто использовать в ArrangeOverride, не обращаясь уже к коллекции InternalChildren заново.
16 фев 19, 15:07    [21811619]     Ответить | Цитировать Сообщить модератору
 Re: WPF: Шпаргалка для создания панели  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19953
И второй вопрос - нужно ли рендерить (да и измерять тоже) элементы, которые заведомо покинули область видимости при расстановке (да и при измерении)?
16 фев 19, 15:55    [21811657]     Ответить | Цитировать Сообщить модератору
 Re: WPF: Шпаргалка для создания панели  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19953
И третий вопрос, правомерен ли комментарий:
"finalSize не может быть больше availableSize"?
16 фев 19, 22:53    [21811876]     Ответить | Цитировать Сообщить модератору
Все форумы / WPF, Silverlight Ответить