Мне нужен совет о том, как спроектировать / реализовать эту пользовательскую панель

#wpf #xaml #panel #itemscontrol

#wpf #xaml #панель #itemscontrol

Вопрос:

Я написал пользовательскую панель, которая отображает свои дочерние элементы, закрепленные вертикально или горизонтально, разделенные перемещающимися разделителями между ними. Поскольку панель Grid предлагает большую часть этой функциональности «из коробки», я просто унаследовал ее.

Чтобы создать макет, после запуска Loaded я делаю следующее:

 1) Read how many children it has and create the appropiate number of rows/colums.
2) Position every existing children in the corresponding row/colum.
3) Create, position and add a GridSplitter for every child.
  

Этот подход выглядит и работает нормально, но он открывает дверь для множества проблем:

  • Поскольку для каждого дочернего элемента добавлен разделитель сетки, количество ожидаемых дочерних элементов в два раза больше. Если кто-то добавил к ней 3 элемента, дочерние элементы.Количество вернет 6.

  • Пользователь мог вставить / удалить что-то не в том месте.

  • Он просто выдает исключение, когда эта сетка используется в качестве ItemsPanel для ItemsControl, поскольку в этом случае WPF (не Silverlight) не допускает прямого манипулирования дочерними элементами.

Эти 3 случая — это те, которые я уже тестировал, но я почти уверен, что возникнет гораздо больше в зависимости от того, что пользователь с этим делает.

Как выясняется, этот класс следует рассматривать как «детали реализации», поэтому реальный вопрос заключается в том, какой элемент управления я должен предоставить пользователю?

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

Я был бы очень признателен за любой совет или некоторые указания, как сделать это правильно.

Заранее спасибо.

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

1. Привет, я бы согласился с ItemsControl. Вы добавляете элементы в свой элемент управления, поэтому это должен быть ItemsControl. что касается добавления элементов — хотели бы вы сохранить как декларативный, так и императивный способы или придерживаться только одного?

2. @Dmitry: Я бы хотел поддерживать оба способа, если это возможно.

3. Есть радикальный способ решить проблему — использовать adorner в отличие от разделителей 🙂 Декларативный вызов вызовет вызов, подобный control. Children.Add(…) для вашей панели элементов (Grid), которая испортит вашу сеточную структуру. Я бы порекомендовал использовать adorners (это решит вашу проблему с количеством визуальных элементов и сделает весь дизайн намного чище). Пожалуйста, дайте мне знать, сработает ли это у вас.

4. @Dmitry: Я решил наследовать от Grid, потому что его «родная» поддержка разделителей, поэтому, если я сделаю это иначе, мне придется написать всю эту часть, я полагаю?

5. @Dmitry: Кроме того, если бы я мог избавиться от разделителей, я думаю, я бы реализовал это как панель.

Ответ №1:

Вы видите, что используя только grid, вы оставляете себе императивный способ добавления только элементов. Как в myCustomGrid1.AddMyItem(***), сетки просто не имеют свойства ItemsSource. ItemsControls делает это, если вам нужна поддержка декларативных источников элементов, т.е. MyControl.ItemsSource = {Привязка …} вы собираетесь выводить свой элемент управления из ItemsControl. Это не двухстрочный вариант — сделать ваши дочерние элементы ItemsPanel доступными для записи — большая проблема — простого способа сделать это нет.

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

Вот что я бы сделал.

  1. Забудьте о ItemsSource amp; items вообще — это не доставит хлопот. Единственным способом добавления / удаления элементов в ваш элемент управления будет AddResiazableItem / RemoveResizbleItem. Вызовы добавят элементы и разделитель (для средних элементов), увеличат количество строк / столбцов вашей сетки в зависимости от ее ориентации, установите Grid.Row / Grid.Прикрепленные к столбцу свойства для ваших дочерних элементов visual. Вы можете сохранить свои фактические объекты внутри, чтобы поддерживать изменение ориентации.

  2. Если на каком-либо этапе вы захотите привязать свой элемент управления к источнику IEnumerable — просто создайте прикрепленное поведение, которое будет перебирать элементы и вызывать AddResiazableItem в цикле.

Приветствия.

P.S. Модераторам — редактор, похоже, сломался, ребята. Я не могу видеть второй элемент. P.S.S. Исправил это после нескольких попыток.

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

1. 1 Похоже, мне придется отказаться от реализации grid… это было так просто: p