Friday, September 21, 2012

Assigning zIndex order to image and text elements on a canvas in Silverlight

Assigning zIndex order to image and text elements on a canvas in Silverlight

I have an image editor in silverlight that allows the user to add, manipulate and delete image and text elements on a canvas. I notice it seems to act strangely when adding new elements sometimes and they will be placed behind an existing element for example. Below is the code for adding image elements, and the order elements method which it calls. I inherited this code from someone else so at times I can't follow what his intention was. The code doesn't seem to do what it is supposed to though.

Can someone suggest a better way to assign a Z-Index value to elements that I am adding?

XAML of my workspace canvas -

<Canvas x:Name="pnlCanvas" HorizontalAlignment="Center" VerticalAlignment="Center" Height="{Binding Path=CanvasHeight, Mode=OneWay,UpdateSourceTrigger=Default}"                         Width="{Binding Path=CanvasWidth, Mode=OneWay, UpdateSourceTrigger=Default}" >                     <ItemsControl ItemsSource="{Binding Path=Elements, Mode=OneWay}"  >                         <ItemsControl.ItemsPanel>                             <ItemsPanelTemplate>                                 <Canvas Background="{Binding Path=CanvasBackground, Mode=OneWay}"                                     Height="{Binding Path=CanvasHeight, Mode=OneWay,UpdateSourceTrigger=Default}"                                     Width="{Binding Path=CanvasWidth, Mode=OneWay, UpdateSourceTrigger=Default}" />                             </ItemsPanelTemplate>                         </ItemsControl.ItemsPanel>                     </ItemsControl>                 </Canvas> 

Adding image element -

private void AddImageElement(object param)     {         bool? gotImage;         string fileName;         BitmapImage imageSource = GetImageFromLocalMachine(out gotImage, out fileName);         OrderElements();          if (gotImage == true)         {             Image image = new Image();             image.Name = fileName;             image.Source = imageSource;             image.Height = imageSource.PixelHeight;             image.Width = imageSource.PixelWidth;             image.MaxHeight = imageSource.PixelHeight;             image.MaxWidth = imageSource.PixelWidth;             image.Cursor = Cursors.Hand;             image.Tag = null;                AddDraggingBehavior(image);             image.MouseLeftButtonUp += element_MouseLeftButtonUp;              this.Elements.Add(image);             numberOfElements++;              this.SelectedElement = image;             this.SelectedImageElement = image;         }     } 

Order Elements -

private void OrderElements()     {         var elList = (from element in this.Elements                       orderby element.GetValue(Canvas.ZIndexProperty)                       select element).ToList<FrameworkElement>();          for (int i = 0; i < elList.Count; i++)         {             FrameworkElement fe = elList[i];             fe.SetValue(Canvas.ZIndexProperty, i);          }          this.Elements = new ObservableCollection<FrameworkElement>(elList);      } 

My end intention once I have this sorted out is to include a layers container like in Photoshop etc. where I will be able to reorder the elements. Hopefully someone can help get me moving in that direction. Basically how do I set the Z-Index correctly because I don't think this is doing it.

Answers & Comments...

Answer: 1

An ItemsControl wraps each element in a <ContentPresenter> tag, so although the ZIndex is set on your element, it doesn't get applied because the ZIndex on the ContentPresenter is what matters

What actually gets rendered looks like this:

<Canvas>     <ContentPresenter>         <Image Canvas.ZIndex="0" />     </ContentPresenter>     <ContentPresenter>         <Image Canvas.ZIndex="1" />     </ContentPresenter>     ... </Canvas> 

To fix the issue, set the ZIndex in the ItemContainerStyle so it gets applied to the ContentPresenter instead of the UI Element

<ItemsControl.ItemContainerStyle>     <Style>         <Setter Property="Canvas.ZIndex" Value="{Binding Canvas.ZIndex}" />     </Style> </ItemsControl.ItemContainerStyle> 

For more information, see the bottom section of my blog post about WPF's ItemsControl

by : Rachelhttp://stackoverflow.com/users/302677




No comments:

Post a Comment

Send us your comment related to the topic mentioned on the blog