Building a Panel-like Custom Control with Attached Properties

136 Views Asked by At

I'm attempting to implement a WPF custom control that displays two collections of FrameworkElement objects in two separate panels. The control derives from ItemsControl and has a Canvas which has IsItemsHost="True" set. Additionally, I have a Collection<FrameworkElement> named OtherItems which I would like to display in a different Canvas.

The custom control defines an attached property: myControl.Position which determines the X position of the item within its canvas. The control also defines a MinValue and MaxValue dependency properties. The control calculates uses the MinValue, MaxValue and control.Position properties to place the UIElement's at the proper position:

<----------0----------> is the result of: MinValue=10, MaxValue=110, myControl.Position=60

I can handle positioning for items that are in the myControl.Items container, but items that are in myControl.OtherItems have a null Parent reference:

public static readonly DependencyProperty PositionProperty =
        DependencyProperty.RegisterAttached("Position", typeof (double), typeof (myControl), 
        new FrameworkPropertyMetadata(0.0, OnPositionChanged));    

public static void OnPositionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    var element = sender as FrameworkElement;
    if (element != null)
    {
        var container = element.Parent as myControl;
        if (container != null)
        {
            container.PositionElement(element);
        }
    }    
}  

<!--Within the myControl's template-->
<Canvas IsItemsHost="True" x:Name="PART_ItemCanvas"/>
<ItemsControl ItemsSource="{TemplateBinding OtherItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas x:Name="PART_OtherItemCanvas"/>
         </ItemsPanelTemplate>
     </ItemsControl.ItemsPanel>
 </ItemsControl.ItemContainerStyle>

<!-- As used -->
<custom:myControl MaxValue="1000" MinValue="-250">
    <custom:myControl.Items>
        <Button myControl.Position="0"/>
        <SomethingElse myControl.Position="25"/>
        <Etc myControl.Position="100"/>
   </custom:myControl.Items>
   <custom:myControl.OtherItems>
       <Button myControl.Position="20"/>
       <Label myControl.Position="300"/>
   </custom:myControl.OtherItems>
</custom:myControl>

How can I handle the call to OnPositionChanged when I do not have access to the sender's parents? I'm assuming this is something that WPF layout controls do all the time, with attached properties like Grid.Row and DockPanel.Dock, but how do they manage it?

0

There are 0 best solutions below