1

How can an AttachedProperty which is a single property defined by an owning parent element, be set with multiple values through several child elements of that parent?

For example:

If I have:

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

Here we have a single DockPanel element and it has a single Dock property. How can it be set to "Top" and then "Bottom" simultaneously?

mkj
  • 2,761
  • 5
  • 24
  • 28
teenup
  • 7,459
  • 13
  • 63
  • 122

3 Answers3

3

It will end up in a method looking like this

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

As you can see, it's actually not set on the parent, but the CheckBox itself, through the static method SetDock on DockPanel and not the parent instance. Doing it in code behind makes this a little clearer, notice how we never use an instance of a DockPanel.

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

Hopefully this was clear, unless your question was how this works "under the hood". In that case, see this question.

Quote from link.

The purpose for this mechanism is to "attach" to other objects information needed by parent objects, not the child objects themselves.

A CheckBox has no use for a Dock property unless it is in a DockPanel. Same goes for Grid.Row, Canvas.Left, Validation.HasError (read only) etc. So basically, the DockPanel is the one needing the information, but it needs all its childs to be able to store it. Hence, it's using an Attached Property for it. If you created a new Panel, called PuneetPanel, and you needed an Angel to calculate the child position, then you could define your own Attached Property, PuneetPanel.Angel inside this panel and all childs could use this without having to be subclassed.

Community
  • 1
  • 1
Fredrik Hedblad
  • 83,499
  • 23
  • 264
  • 266
  • So, I don't understand what is the use of "AttachedProperty", what does it do, this could also have been done using some property on CheckBox when ultimately it is stored with the CheckBox. Why DockPanel is defining and owning the property and maintaining a property identifier with it. – teenup Nov 08 '10 at 07:15
0

This is a very nice question. The answer lies in how the AttchedProperty works. The AttachedProperty is used by the parent to render a child. Before rendering the child, the parent looks out for any attached property defined on child and applies to the child.

I found this from msdn which might be useful for you ::

DockPanel defines the DockPanel.Dock attached property, and DockPanel has class-level code as part of its rendering logic (specifically, MeasureOverride and ArrangeOverride).
A DockPanel instance will always check to see whether any of its immediate child elements have set a value for DockPanel.Dock. If so, those values become input for the rendering logic applied to that particular child element....

You can see this link to get detailed overview ::
http://http://msdn.microsoft.com/en-us/library/ms749011.aspx

Hope it helps you!!

  • I have already read this msdn page, from reading this page only, I got this doubt. I know that the parent will query the childs for that property, but in which object the different values for the property will be saved ? Because the property is single member variable in the owning class and can have only one value at a time. What I guess is the property will be stored separately in the two checkboxes in this example, but then the CheckBox does not have any Dock property itself. – teenup Nov 08 '10 at 05:09
  • Yes an attached property can only have one single value at a time for one DependencyObject (CheckBox) instance. It will not be stored in the object directly. The WPF engine maintains a lookup table internally where each object instance is related to attached properties that have been set. When you get the values using XAML or the get accessor method you actly make WPF lookup the values in the table. From the outside it *looks* as if you'd retrieved if from the object directly. – bitbonk Nov 08 '10 at 19:28
0

For your own custom attached properties there are two options to achieve what you are looking for:

1. If the number of combinations of settable values are not to complex you could make your attached property of type enum that has the FlagsAttribute set. You can the combines the values you want to set using bitwise-or |:

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

And its usage in code:

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

This has one small proplem though, you can not do the above in xaml directly, you would have to write a MarkupExtension that can convert string to flagged enum values. Its usage would then look like this:

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

2. Since attached properties can be of any type, they can of course also be complex types (with multiple subproperties) or even collections, so it is easily possible to do something like this:

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

If you have defined your attached property that way, you do not need any converters for xaml, you can use it directly:

<CheckBox>
    <src:MyCustomPanelOrWhatever.MultiDock>
        <src:MultiDock.Left/>
        <src:MultiDock.Bottom/>
    </src:MyCustomPanelOrWhatever.MultiDock>
</CheckBox>
shriek
  • 5,157
  • 2
  • 36
  • 42
bitbonk
  • 48,890
  • 37
  • 186
  • 278