none
InkCanvas Z-order support RRS feed

  • Question

  • Hello,

    Is it possible to implement Z-order functionality with *ink and objects* in InkCanvas?

    Specifically be able to have, for example (from lowest layer to highest layer):

    a. a text box

    b. some ink overlapping the text box

    c. some shape overlapping (b)

    etc...

    From what I've seen, "ink" in an InkCanvas is always rendered "on top".  What would be involved in creating this functionality?

    Thank you,

    Boris

    Sunday, January 14, 2007 11:51 AM

Answers

  • Hi Boris,

    here is how the z-order funtionality works for ink and elements in InkCanvas works:

    1) the z-order of elements relative to each other can be controlled by setting the Panel.ZIndex property on the element

    2) Ink is always rendered on top of InkCanvas's child elements

    3) If you want elements to be rendered on top of the ink, you have two choices:

      a) make the element a sibling of InkCanvas with a higher Panel.ZIndex

      b) render the element in InkCanvas's AdornerLayer (which is always on top of the ink)

     

    Please let me know if you have more questions about this.

    Thanks, Stefan Wick

    Sunday, January 14, 2007 2:16 PM

All replies

  • Hi Boris,

    here is how the z-order funtionality works for ink and elements in InkCanvas works:

    1) the z-order of elements relative to each other can be controlled by setting the Panel.ZIndex property on the element

    2) Ink is always rendered on top of InkCanvas's child elements

    3) If you want elements to be rendered on top of the ink, you have two choices:

      a) make the element a sibling of InkCanvas with a higher Panel.ZIndex

      b) render the element in InkCanvas's AdornerLayer (which is always on top of the ink)

     

    Please let me know if you have more questions about this.

    Thanks, Stefan Wick

    Sunday, January 14, 2007 2:16 PM
  • Stefan - thanks for your answer.

    None of these options seems to provide the type of functionality I was looking for.  Basically I wanted to be able to have a child element of InkCanvas (like a textbox), sandwiched between ink strokes.   In other words I want to have a fine granularity in controling who goes on top of what...    seems like the only thing that will get me there is to implement my own InkCavas from the building blocks provided (InkPresenter, DynamicRenderer..etc)

    I'm looking into creating a "layered" InkCanvas, functioning in a similar way to how layers work in Adobe Photoshop (if you're familiar with that).  Among the requirements would be to be able to reorder these layers (decide the z-index of each layer), and maybe even within each layer decide the z-index of the containing elements (ink and rest). 

    If you have any other advice to get me closer to this goal, I'm all ears :-)

    Thank you! 

    Boris

    Monday, January 15, 2007 1:35 PM
  • Hi Boris,

    if I understand you correctly you basically want to assign a different z-order to different subsets of your ink strokes. For that you would need one InkPresenter (or InkCanvas which is built on top of InkPresenter) for each layer of ink.

    You go could down the route of creating your own control with multiple InkPresenters, but you might be able to accomplish what you want by layering a bunch on InkCanvas elements on top of each other.

    As a starting point, here is a simple user control that can host ink and elements in different levels and allows you to move them between the levels:

    XAML:

    <UserControl x:Class="WindowsApplication1.UserControl1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Canvas Name="mainCanvas">
          <InkCanvas Name="lowerLayer" Width="{Binding ElementName=mainCanvas,Path=ActualWidth}"
                     Height="{Binding ElementName=mainCanvas,Path=ActualHeight}"
                     Background="Yellow" StrokeCollected="OnStroke" StrokeErasing="OnStrokeErasing"/>
          <InkCanvas Name="upperLayer" Width="{Binding ElementName=mainCanvas,Path=ActualWidth}"
                     Height="{Binding ElementName=mainCanvas,Path=ActualHeight}"
                     Background="Transparent" IsHitTestVisible="False" EditingMode="None" />
        </Canvas>
    </UserControl>

    C# code behind to manage the layers of ink and elements:

    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Ink;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;

    namespace WindowsApplication1
    {
        public partial class UserControl1 : System.Windows.Controls.UserControl
        {
            private StrokeCollection _strokes = new StrokeCollection();

            public UserControl1()
            {
                InitializeComponent();
            }

            private void OnStroke(object sender, InkCanvasStrokeCollectedEventArgs e)
            {
                _strokes.Add(e.Stroke);
            }

            private void OnStrokeErasing(object sender, InkCanvasStrokeErasingEventArgs e)
            {
                _strokes.Remove(e.Stroke);
            }

            public StrokeCollection Strokes
            {
                get { return _strokes; }
            }

            public void AddElementBehindInk(UIElement element)
            {
                lowerLayer.Children.Add(element);
            }

            public void AddElementOnTop(UIElement element)
            {
                upperLayer.Children.Add(element);
            }

            public void MoveElementBehind(UIElement element)
            {
                if (upperLayer.Children.Contains(element))
                {
                    upperLayer.Children.Remove(element);
                    lowerLayer.Children.Add(element);
                }
            }

            public void MoveElementOnTop(UIElement element)
            {
                if (lowerLayer.Children.Contains(element))
                {
                    lowerLayer.Children.Remove(element);
                    upperLayer.Children.Add(element);
                }
            }

            public void MoveStrokeOnTop(Stroke stroke)
            {
                if (lowerLayer.Strokes.Contains(stroke))
                {
                    lowerLayer.Strokes.Remove(stroke);
                    upperLayer.Strokes.Add(stroke);
                }
            }

            public void MoveStrokeBehind(Stroke stroke)
            {
                if (upperLayer.Strokes.Contains(stroke))
                {
                    upperLayer.Strokes.Remove(stroke);
                    lowerLayer.Strokes.Add(stroke);
                }
            }
        }
    }

     

    Thanks, Stefan Wick

     

    Wednesday, January 17, 2007 4:04 PM
  • I am looking to move the InkPresenter in the InkCanvas to have a ZIndex that is lower than the Children of the InkCanvas. In other words, I want to move the Ink so that it is displayed under the images and user controls that are added to the InkCanvas as Children.

    I was wondering if there is a way to edit the Control Template of the InkCanvas to achieve this?

    I do not want to use 2 controls as has been suggested here (one being the InkCanvas for displaying and managing Ink, and another for the other controls) because I want to be able to select, delete, and manage both Ink Strokes and other controls together. The InkCanvas already has built in Selection functionality that I can use.

     

     

    Thanks for your time.

    Monday, December 12, 2011 6:23 PM
  • Hi AnonymousMe83,

    Did you able to find any solution for z-index ?

    Monday, December 10, 2018 7:37 AM