Как AttachedProperty может иметь несколько значений? - PullRequest
1 голос
/ 08 ноября 2010

Как можно AttachedProperty , который является одним свойством, определенным родительским элементом-владельцем, устанавливать с несколькими значениями через несколько дочерних элементов этого родителя?

Например:

Если у меня есть:

<DockPanel>
  <CheckBox DockPanel.Dock="Top">Hello</CheckBox>
  <CheckBox DockPanel.Dock="Bottom">World</CheckBox>
</DockPanel>

Здесь у нас есть один элемент DockPanel, и у него есть одно свойство Dock. Как можно одновременно установить «Верх», а затем «Низ»?

Ответы [ 3 ]

3 голосов
/ 08 ноября 2010

В конечном итоге это будет выглядеть примерно так

public class DockPanel : Panel
{
    public static readonly DependencyProperty DockProperty;
    // ...
    public static void SetDock(UIElement element, Dock dock)
    {
        element.SetValue(DockProperty, value);
    }
}

Как вы можете видеть, на самом деле он установлен не на родительском объекте, а на самом CheckBox через статический метод SetDock на DockPanel, а не на родительский экземпляр. Выполнение этого в коде позади делает это немного яснее, обратите внимание, как мы никогда не используем экземпляр DockPanel.

DockPanel.SetDock(checkBox1, Dock.Top);
DockPanel.SetDock(checkBox2, Dock.Bottom);

Надеюсь, это было понятно, если только ваш вопрос не был в том, как это работает "под капотом". В этом случае см. этот вопрос.

Цитата из ссылки.

Целью этого механизма является «прикреплять» к другим объектам информацию нужны родительские объекты, а не сами дочерние объекты.

CheckBox не использует свойство Dock, если оно не находится в DockPanel. То же самое касается Grid.Row, Canvas.Left, Validation.HasError (только для чтения) и т. Д. Итак, в основном, DockPanel - это та, которая нуждается в информации, но ей нужны все дочерние элементы, чтобы иметь возможность ее хранить. Следовательно, он использует свойство Attached для него. Если вы создали новую Panel с именем PuneetPanel и вам нужен Angel для вычисления дочерней позиции, то вы можете определить собственное присоединенное свойство PuneetPanel.Angel внутри этой панели, и все дочерние элементы могут использовать его без необходимости использовать подклассы.

0 голосов
/ 08 ноября 2010

Для ваших собственных пользовательских свойств есть два варианта для достижения того, что вы ищете:

1. Если количество комбинаций настраиваемых значений не является сложным, вы можете сделать ваше присоединенное свойство типа enum с установленным FlagsAttribute . Вы можете объединить значения, которые вы хотите установить, используя побитовый или |:

[Flags]
public enum MultiDock
{
  Left,
  Top,
  Right,
  Bottom
}

И его использование в коде:

MyCustomPanelOrWhatever.SetMultiDock(MultiDock.Left | MultiDock.Bottom);

У этого есть одна небольшая проблема, хотя вы не можете сделать это напрямую в xaml, вам нужно написать MarkupExtension , который может преобразовать строку в помеченные значения перечисления. Его использование будет выглядеть следующим образом:

<CheckBox src:MyCustomPanelOrWhatever.MulitDock="{src:FlaggedEnum Left|Bottom}"  />

2. Поскольку присоединенные свойства могут быть любого типа, они, конечно, также могут быть сложными типами (с несколькими подгруппами) или даже коллекциями, поэтому легко можно сделать что-то вроде этого:

MyCustomPanelOrWhatever.SetMultiDock(new List<MultiDock> { MultiDock.Left, MultiDock.Bottom });

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

<CheckBox>
    <src:MyCustomPanelOrWhatever.MultiDock>
        <src:MultiDock.Left/>
        <src:MultiDock.Bottom/>
    </src:MyCustomPanelOrWhatever.MultiDock>
</CheckBox>
0 голосов
/ 08 ноября 2010

Это очень хороший вопрос. Ответ заключается в том, как работает AttchedProperty. AttachedProperty используется родителем для визуализации дочернего элемента. Перед рендерингом дочернего элемента родительский объект ищет любое прикрепленное свойство, определенное для дочернего элемента, и применяется к дочернему элементу.

Я нашел это из MSDN, который может быть полезен для вас ::

DockPanel определяет вложенное свойство DockPanel.Dock, а DockPanel имеет код уровня класса как часть своей логики рендеринга (в частности, MeasureOverride и ArrangeOverride).
Экземпляр DockPanel всегда проверяет, установил ли какой-либо из его непосредственных дочерних элементов значение для DockPanel.Dock. Если это так, эти значения становятся входными данными для логики рендеринга, применяемой к этому конкретному дочернему элементу ....

Вы можете увидеть эту ссылку, чтобы получить подробный обзор ::
http://http://msdn.microsoft.com/en-us/library/ms749011.aspx

Надеюсь, это поможет вам !!

...