0

I have a problem when I'm trying to draw a line with the MVVM-Pattern in WPF. I followed this example: Drawing line on a canvas in WPF MVVM doesn't work

The Problem I have, is that I want to draw lines on a video control that is already implemented, which I can't use as ItemsPanelTemplate. So my code currently looks like this:

xaml

<ContentControl>
    <views:ExtendedMediaElement x:Name="MediaPlayer" Grid.Row="0"  ScrubbingEnabled="True" LoadedBehavior="Manual" UnloadedBehavior="Stop"
                    MediaLength="{Binding MediaLength, Mode=OneWayToSource}"
                    MediaPosition="{Binding MediaPosition, Mode=TwoWay}"
                    EndPosition="{Binding EndPosition, Mode=OneWay}"/>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseDown">
            <cal:ActionMessage MethodName="MouseDown">
                <cal:Parameter Value="$eventArgs"/>
                <cal:Parameter Value="{Binding ElementName=ItemControl}"/>
            </cal:ActionMessage>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ContentControl>

<ItemsControl x:Name="ItemControl" ItemsSource="{Binding Path=Lines}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Line X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" Stroke="{Binding Stroke}" StrokeThickness="{Binding StrokeThickness}"></Line>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

ViewModel

private ObservableCollection<Line> _lines;
public ObservableCollection<Line> Lines
{
    get { return _lines; }
    set
    {
        if (_lines != value)
        {
            _lines = value;

            NotifyOfPropertyChange("Lines");
        }
    }
}

public void MouseDown(MouseButtonEventArgs e, System.Windows.Controls.ItemsControl lineArea)
{
    System.Windows.Point p = e.GetPosition(lineArea);

    if (!isFirstPointSet)
    {
        firstClickPoint = p;
        isFirstPointSet = true;
        return;
    }

    Line l = new Line();
    l.X1 = firstClickPoint.X;
    l.Y1 = firstClickPoint.Y;
    l.X2 = p.X;
    l.Y2 = p.Y;
    l.Stroke = System.Windows.Media.Brushes.Black;
    l.StrokeThickness = 4;

    Lines.Add(l);

    firstClickPoint = p;
}

Now the first line I draw is always perfectly placed on the Click-Coordinates, but the second line has an offset on the X-Coordinate. The thrid line is often not even visible any more.

Thanks in advance for your help! Niko

Community
  • 1
  • 1
greece57
  • 421
  • 1
  • 6
  • 16
  • Just find that you forgot to set the ItemsPanel property. You can copy the code from that link and verify if it fixes the problem. See my updated answer – kennyzx Jun 01 '16 at 18:17
  • @kennyzx I worked around the problem on the next day by just raising an event with a Line as Parameter and publishing the event so that the .xaml.cs File can handle the event and draw the line directly on the canvas. I should maybe answer my own question with that workaround but I hesitaded since I think it doesn't apply to the MVVM Pattern, does it? – greece57 Jun 03 '16 at 10:12
  • 1
    Pure MVVM is hard to achieved and often impractical, so don't worried if the code "breaks" MVVM. But for this case, your workaround does not answer why you ran into this problem so I think it is not appropriate to post it as an answer. – kennyzx Jun 03 '16 at 10:18

1 Answers1

2

Take a look at the below example, each item in an ItemsControl are at different position. If the first line is drawn on canvas 32, the second line will be drawn on canvas 33. They are not drawn on the same, big canvas as you might expected.

You need to set the ItemsPanel property just like the answer in the link you provided.

enter image description here

kennyzx
  • 12,845
  • 6
  • 39
  • 83