Я удивлен, что никто еще не предложил с использованием фактического FlowDocument , чтобы выложить ваш пользовательский интерфейс.
Я использовал FlowDocument
прежде, чтобы достигнуть сложных аранжировок. Он работает довольно хорошо, за исключением того, что некоторые свойства наследуются (например, TextElement.FontSize
). Это не сложно обойти.
В вашем случае просто разбейте # 2 на отдельный UserControl для каждого раздела, а внутри FlowDocument используйте InlineUIContainer, чтобы обернуть каждый раздел.
<Window>
<DockPanel>
... toolbars, etc ...
<FlowDocumentScrollViewer ...>
<FlowDocument>
...
<InlineUIContainer>
<my:PartialNumberTwo DataContext="{Binding ...}" />
</InlineUIContainer>
...
Конечно, существуют ограничения на то, что может делать FlowDocument, поэтому он может не работать в вашем сценарии.
Чрезвычайно гибкий вариант заключается в создании настраиваемой панели, которая размещает свои дочерние элементы в стиле WrapPanel, но делает это путем подгонки прямоугольников и, прежде чем начать, выделяет любую область, перекрытую собственными братьями и сестрами панели, как недоступную.
Такая панель будет использоваться так:
<Grid ...>
... RowDefinitions, ColumnDefinitions ...
<panels:WrapIntoRemainingSpacePanel RowSpan="4" ColumnSpan="3"> <!-- fill whole grid -->
<my:Control2Part1 />
<my:Control2Part2 />
<my:Control2Part3 />
<my:Control2Part4 />
</panels:WrapIntoRemainingSpacePanel>
<my:Control1 Grid.Row="0" Grid.ColumnSpan="3" />
<my:Control3 Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2" />
<my:Control4 Grid.Row="3" Grid.RowSpan="2" />
Эта панель будет реализована следующим образом:
- В ArrangeOverride запланируйте обратный вызов Dispatcher.BeginInvoke для выполнения фактического упорядочивания и создания отчета в полном размере
- В обратном вызове получите прямоугольники, представляющие ограничивающие рамки всех моих братьев и сестер в координатном пространстве моего родителя.
- Сортировать координаты Y (сверху и снизу) всех размещенных прямоугольников
- Поместите каждого дочернего элемента, найдя первую координату Y в отсортированном списке, в котором где-то есть горизонтальное пространство для содержимого, и поместив его как можно левее
- Мониторинг VisualTransform братьев и сестер для изменений, если любой вызов InvalidateArrange ()