Friday 23 May 2014

Custom Panel with Z-Ordering in Xaml (WPF)

In this article we are going to see how to create a custom panel with Z-Order, First Let we see what is Z-Order ? Z-Order means the object which have least Z-Order is arranged as First layer, and the Object which have high Z-Order then it is arranged at last on the Top of the Layer to see in example below are the are two example screen shots with code in canvas panel

Normal - Z-Index
**************




Xaml Code :
***********
  <Grid>       
        <Canvas>           
            <Border   Height="185" Width="160" Background="Tomato"/>
            <Border   Height="170" Width="170" Background="Gray"/>
            <Border   Height="150" Width="180" Background="Orange"/>
            <Border   Height="130" Width="190" Background="SteelBlue"/>
        </Canvas>       

    </Grid>


Set Z-Index
**********

                                          
Xaml Code:
**********
  <Grid>       
        <Canvas>           
            <Border Panel.ZIndex="98"  Height="185" Width="160" Background="Tomato"/>
            <Border Panel.ZIndex="97" Height="170" Width="170" Background="Gray"/>
            <Border Panel.ZIndex="96" Height="150" Width="180" Background="Orange"/>
            <Border Panel.ZIndex="95" Height="130" Width="190" Background="SteelBlue"/>
        </Canvas>       

    </Grid>


Now From the above code you can see that the Z-index set in the second code so based on that the panel which have high z-index place or render on the Top , so now we are going to create a panel like this which have the Z-Order property.

Custom Panel with Z-Order
     In the Following code you can see how to create a custom panel with Z-Order index i.e the order of render child elements changed. It can reflect in design time also, when the property is changes the rendering can be seen in design time


OrderingPanel.cs
***************
class OrderingPanel:Panel
    {
        private Dictionary<int, int> _zindexorder = new Dictionary<int, int>();
              
        public bool IsZorder
        {
            get { return (bool)GetValue(IsZorderProperty); }
            set { SetValue(IsZorderProperty, value); }
        }

       
        public static readonly DependencyProperty IsZorderProperty =
            DependencyProperty.Register("IsZorder", typeof(bool), typeof(OrderingPanel), new                 FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure |
FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure |
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                OnZOrderPropertyChanged));


private static void OnZOrderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            OrderingPanel pan = d as OrderingPanel;
            ReAddChild(pan);
           
        }

        private static void ReAddChild(OrderingPanel pan)
        {
            for (int i = 0; i < pan.InternalChildren.Count; i++)
            {
                pan.RemoveVisualChild(pan.InternalChildren[i]);
            }
            for (int i = 0; i < pan.InternalChildren.Count; i++)
            {
                pan.AddVisualChild(pan.InternalChildren[i]);
            }
        }

        public OrderingPanel()
        {
           
        }

        protected override System.Windows.Size MeasureOverride(Size availableSize)
        {
            if (availableSize.Height == double.PositiveInfinity && availableSize.Width ==                          double.PositiveInfinity)
                return Size.Empty;

            for (int i = 0; i < InternalChildren.Count; i++)
            {
                InternalChildren[i].Measure(new Size(double.PositiveInfinity,                                                double.PositiveInfinity));
            }

            return availableSize;
        }

        protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
        {
            for (int i = 0; i < InternalChildren.Count; i++)
            {
                InternalChildren[i].Arrange(new Rect(new Point(Margin.Left, Margin.Top),                              InternalChildren[i].DesiredSize));
            }
            return finalSize;
        }

        protected override System.Windows.Media.Visual GetVisualChild(int index)
        {
            if (IsZorder)
            {
                return InternalChildren[InternalChildren.Count - 1 - index];
            }
            else
            {
                return InternalChildren[index];
            }
        }

        protected override int VisualChildrenCount
        {
            get
            {
                return this.InternalChildren.Count;
            }
        }

    }




Normal Order
***********

                                                

Xaml Code:
**********
<Grid>     
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <local:OrderingPanel  IsZorder="False" x:Name="zpanel">           
            <Border Margin="45,15,10,10"  Height="185" Width="160" Background="Tomato"/>
            <Border Margin="45,15,10,10"  Height="170" Width="170" Background="Gray"/>
            <Border Margin="45,15,10,10"  Height="150" Width="180" Background="Orange"/>
            <Border Margin="45,15,10,10"  Height="130" Width="190" Background="SteelBlue"/>
        </local:OrderingPanel>       
        <Button Grid.Column="1" Width="100" Height="50" Click="Button_Click">Change order</Button>

    </Grid>


Z-Order:
*******
Change the Property IsZorder to True to change the order



Xaml Code:
**********


<Grid>     
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <local:OrderingPanel  IsZorder="True" x:Name="zpanel">           
            <Border Margin="45,15,10,10"  Height="185" Width="160" Background="Tomato"/>
            <Border Margin="45,15,10,10"  Height="170" Width="170" Background="Gray"/>
            <Border Margin="45,15,10,10"  Height="150" Width="180" Background="Orange"/>
            <Border Margin="45,15,10,10"  Height="130" Width="190" Background="SteelBlue"/>
        </local:OrderingPanel>       
        <Button Grid.Column="1" Width="100" Height="50" Click="Button_Click">Change order</Button>

    </Grid>



From this article you can learn how to create a custom panel with Z-Ordering

No comments:

Post a Comment