-1

For my project I am going to have some lines drawn, and I need to check if they will be in the Visible X and Y - so I thought I'd use a multi value converter that would return the line if it is inside the X,Y else return null or something. I want to know how to bind the X1, X2, etc of the line to the returned line object? In the following XAML you can see I try to pass the Lines observable collection with the visible min max etc, and I would like to see if the last line is within the boundary. If so return it (currently all of them return for testing purposes), and I want to bind the Line with the returned line. Wondering how to go about this...

The goal for the entire program is to eventually map the path a little robot car took - using these lines. And eventually I wanted some sort of zoom capabilities so I am trying to create the lines via binding.

My XAML items control looks like

    <ItemsControl x:Name="Items">
    <ItemsControl.ItemsSource>
        <MultiBinding Converter="{StaticResource conv}">
            <Binding Path="Lines"/>
            <Binding Path="VisibleMinX"/>
            <Binding Path="VisibleMinY"/>
            <Binding Path="VisibleMaxX"/>
            <Binding Path="VisibleMaxY"/>

        </MultiBinding>
    </ItemsControl.ItemsSource>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Line X1="{Binding X1}" X2="{Binding X2}" Y1="{Binding Y1}" Y2="{Binding Y2}" Stroke="Black" StrokeThickness="2"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    </ItemsControl>

My View model (code behind of main is empty)

class VM : INotifyPropertyChanged
{
    public AddLineCommand addlinecommand { get; set; }

    public VM()
    {
        VisibleMinX = 0;
        VisibleMinY = 0;
        VisibleMaxX = 300;
        VisibleMaxY = 300;
        //test
        CreateLine(100, 100, 150, 150);
        CreateLine(150, 150, 200, 280);

        addlinecommand = new AddLineCommand(this);
    }
    private ObservableCollection<Line> lines = new ObservableCollection<Line>();
    public ObservableCollection<Line> Lines
    {
        get
        {
            return lines;
        }
    }
    public void CreateLine(int x1, int y1, int x2, int y2)
    {
        Line line = new Line();
        line.X1 = x1;
        line.Y1 = y1;
        line.X2 = x2;
        line.Y2 = y2;

        line.StrokeThickness = 2;

        SolidColorBrush black = new SolidColorBrush();
        black.Color = Colors.Black;

        line.Stroke = black;

        Lines.Add(line);
        OnPropertyChanged("Lines");
    }
    public void AddLine()
    {
        CreateLine(0, 0, 100, 100);
    }

    private int _VisibleMinX;

    public int VisibleMinX
    {
        get { return _VisibleMinX; }
        set { _VisibleMinX = value; }
    }

    private int _VisibleMaxX;

    public int VisibleMaxX
    {
        get { return _VisibleMaxX; }
        set { _VisibleMaxX = value; }
    }

    private int _VisibleMinY;

    public int VisibleMinY
    {
        get { return _VisibleMinY; }
        set { _VisibleMinY = value; }
    }

    private int _VisibleMaxY;

    public int VisibleMaxY
    {
        get { return _VisibleMaxY; }
        set { _VisibleMaxY = value; }
    }




    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}

}

And my converter

class conv : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        ObservableCollection<Line> line = (ObservableCollection<Line>)values[0];
        int MinX = (int)values[1];
        int MinY = (int)values[2];
        int MaxX = (int)values[3];
        int MaxY = (int)values[4];

        return line[line.Count-1];  //returning last line obj
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Fivestar
  • 323
  • 1
  • 5
  • 18
  • 1
    Unclear question. Your converter is returning one line, so your `ItemsSource` now consists of one single line (single object instead of collection). – AnjumSKhan Jun 13 '16 at 00:29
  • What you are trying to show in your IC ? – AnjumSKhan Jun 13 '16 at 00:45
  • @AnjumSKhan Umm yes it should be a single line object. In the converter I will eventually do some editing or processing of the numbers - its really simple for now to get it to actually work. The single line it returns, I want to bind the new line im creating in the items control with the x1, x2, y1, y2 values of that line. If that makes sense? – Fivestar Jun 13 '16 at 01:00
  • 1
    I still can't figure out what you are trying to do, but this should solve your problem : replace `return` with `return new ObservableCollection(){line[line.Count-1]};` – AnjumSKhan Jun 13 '16 at 01:21
  • @AnjumSKhan That fixed the problem at hand yes but - it replaces the old line with the new line values which makes sense because I now realise my logic is wrong. I want to be able to add lines to the observable collection, and when I add that line it gets drawn. The reason for the visible x and y stuff is eventually we want a zoom in and out type thing. I initially thought the in the items source would create a NEW line each time but I was wrong, and tips on where to go from here? – Fivestar Jun 13 '16 at 02:44

1 Answers1

0

First of all, like what AnjumSKhan has said, what you are doing is not making a lot of sense. Secondly, I just wanted to voice out my opinion that, if your application logic itself involves drawing-related stuff, then you can simply do the logic in the ViewModel itself. (I do know there will be people who would disagree with me here)

So, what I mean is that - if filtering/modifying that Lines collection, based on some valid VisibleMinX etc, is part of the business logic, do it right at the ViewModel.

Unfortunately, at this point of time, it is still very unclear what your objectives are, so I could not really post some kind of sample codes. I'll probably post an update if you happen to update your question.

Jai
  • 8,165
  • 2
  • 21
  • 52
  • Eventually my goal is to create a program that is going to map the path that a little robot car took using lines. Since a user may go say to the right a far distance we need some zoom in our feature later on which is why I am trying to create the lines via binding so the zoom will be easier to implement. I am a student and new to C# and MVVM. Hope that gives a better explanation? – Fivestar Jun 13 '16 at 15:34
  • If you are placing Polylines into a canvas, you can use transform to show different parts, at different scale (zoom) levels. There is no need to manually calculate which lines (or which part of the lines) to be visually visible. – Jai Jun 14 '16 at 00:36