1/21/08

How to change the Z order of WPF controls at runtime

It's as simple as this -- keep track of the highest zIndex and before assigning it to the control that needs to have the highest ZIndex - increment it, that way you ensure that the current control has the highest ZIndex and also if there is a set Z order, you are not going to mess it up.

The code would look something like this:


//set
var zIndex = ((YourCurrentControlType)sender).GetValue(Parent.ZIndexProperty);

//get
someControl.SetValue (Parent.ZIndexProperty, zIndex++);

In my previous post I wanted to move WPF controls at runtime on canvas by selecting them with the mouse and dragging them to a new location. The problem was that the dragged control, if overlapped the other control, would appear to be behind it, if its Z order was lower. So I needed to change the Z order of the control that is being dragged.


L O G I C


Current control should have the highest Z order, so introduce an variable that keeps track of the highest Z order and assigns it to the current control that needs it (incrementing it beforehand, to ensure that it has the highest one).



I M P L E M E N T A T I O N

I used the code from my previous post on how to move WPF controls and modified a couple of things:

1. Introduce the z Order variable by adding it as the ZIndex property to the public class Element

  private int zIndex = 0;
public int ZIndex
{
get { return this.zIndex; }
set { this.zIndex = value; }
}

2. add a line of code to function rect1_MouseLeftButtonDown() to capture the current Z order:


private void rect1_MouseLeftButtonDown(object sender,
MouseButtonEventArgs e)
{
//capture the last highest z index
//before pointing to new current element

int newZIndex = (int)((Border)sender).GetValue(Canvas.ZIndexProperty);
this.current.ZIndex = newZIndex > this.current.ZIndex ?
newZIndex :
this.current.ZIndex;

//capture the new current element
this.current.InputElement = (IInputElement)sender;

}
3.Assign the highest Z order to the current control in Canvas_MouseMove:




private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if ( e.LeftButton == MouseButtonState.Pressed &&
current.InputElement != null)
{
//increment z-Order and pass it to the current element,
//so that it stays on top of all other elements

((Border)this.current.InputElement).SetValue(Canvas.ZIndexProperty,
this.current.ZIndex++);

if (this.current.IsDragging)
Drag(sender);//shortened, see how to drag in previous post
}
}

And that's it...pretty simple.
_____________________________________________



4 comments:

  1. Anonymous11/17/2009

    would you have the vb.net version to this?

    ReplyDelete
  2. well, was gonna write this out real quick for you, but neither of my computers have VB.NET installed, I got one more at home, I'll look tonight, if I have it, it shouldn't take too long to write this out.
    Also, you could always start C#.Net project, paste all the code in there, compile and open the binary in Reflector. In Reflector switch the view to VB and it'll convert it :)

    ReplyDelete
  3. Cool, Spasibo za SetValue(Canvas.ZIndexProperty)

    ReplyDelete