2

I am using DrawingContext.DrawLine function to draw lines. But it seems like lines affecting the position of other lines on canvas. So I need to add different z-index values to all lines. Is there any way to draw lines with different z-index so they do not affect the position of other lines. Or is there any other method available to draw lines, like to draw text I have replaced DrawText method with TextBlock.

Below is the sample code I am using right now:

DrawingGroup dGroup = new DrawingGroup();
DrawingContext dc = dGroup.Open()
dc.DrawLine(penScaleMarker, new Point((float)newPointX, (float)newPointY), new Point((float)newMinorEndX, (float)newMinorEndY));
croxy
  • 4,082
  • 9
  • 28
  • 46
  • In a DrawingContext, the z-order is determined by the order in which you draw elements. It isn't clear why exactly you are using a DrawingContext at all. Why not add Line elements to a Canvas? – Clemens Nov 21 '16 at 11:07
  • Actually the position and number of lines to draw are dynamic so is it possible to add line element to canvas ? If yes then please let me know how to do that. – Deepika Porwal Nov 21 '16 at 12:11

1 Answers1

5

In order to add a dynamic collection of shapes to a Canvas, you would typically declare an ItemsControl with a Canvas as its ItemsPanel. The ItemsSource property of the Canvas would be bound to a collection of data items which represent shape data in an abstract manner. The ItemTemplate of the ItemsControl would be responsibe for visualizing each individual item.

<ItemsControl ItemsSource="{Binding ShapeItems}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Path Data="{Binding Geometry}"
                  Stroke="{Binding Stroke}"
                  StrokeThickness="2"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

The view model that defines the data item class would look like shown below. Note that besides the Geometry and Stroke properties, you might have other properties that define the visual appearance.

public class ShapeItem
{
    public Geometry Geometry { get; set; }
    public Brush Stroke { get; set; }
}

public class ViewModel
{
    public ObservableCollection<ShapeItem> ShapeItems { get; }
        = new ObservableCollection<ShapeItem>();
}

and you might instantiate and initialize it in your MainWindow like this:

public MainWindow()
{
    InitializeComponent();

    var vm = new ViewModel();

    vm.ShapeItems.Add(new ShapeItem
    {
        Geometry = new LineGeometry(new Point(100, 100), new Point(200, 200)),
        Stroke = Brushes.Green
    });

    vm.ShapeItems.Add(new ShapeItem
    {
        Geometry = new LineGeometry(new Point(200, 200), new Point(100, 300)),
        Stroke = Brushes.Red
    });

    DataContext = vm;
}

You may now add a ZIndex property to the ShapeItem class

public class ShapeItem
{
    public Geometry Geometry { get; set; }
    public Brush Stroke { get; set; }
    public int ZIndex { get; set; }
}

and add the following to the ItemsControl:

<ItemsControl ItemsSource="{Binding ShapeItems}">
    ...
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Panel.ZIndex" Value="{Binding ZIndex}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

The ShapeItem class would also have to implement the INotifyPropertyChanged interface in case its properties change their values after having been added to the collection.

Clemens
  • 123,504
  • 12
  • 155
  • 268