i have two grid on Window form , i need to show mapping by lines between cell/s from one grid to other grid when user click on first grid cell and also this functionality wo
Ok. Im posting this as an answer because the OP asked for it.
This is my WPF take on that:
Code Behind:
public partial class DataGridConnectors : Window
{
public List Items1 { get; set; }
public List Items2 { get; set; }
public List Connectors { get; set; }
private ObservableCollection _visibleConnectors;
public ObservableCollection VisibleConnectors
{
get { return _visibleConnectors ?? (_visibleConnectors = new ObservableCollection()); }
}
public DataGridConnectors()
{
Connectors = new List();
InitializeComponent();
Loaded += OnLoaded;
Items1 = Enumerable.Range(0, 1000).Select(x => "Item1 - " + x.ToString()).ToList();
Items2 = Enumerable.Range(0, 1000).Select(x => "Item2 - " + x.ToString()).ToList();
DataContext = this;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
var scrollviewer1 = FindDescendent(DG1).FirstOrDefault();
var scrollviewer2 = FindDescendent(DG2).FirstOrDefault();
if (scrollviewer1 != null)
scrollviewer1.ScrollChanged += scrollviewer_ScrollChanged;
if (scrollviewer2 != null)
scrollviewer2.ScrollChanged += scrollviewer_ScrollChanged;
}
private void scrollviewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
var visiblerows1 = GetVisibleContainers(Items1, DG1.ItemContainerGenerator);
var visiblerows2 = GetVisibleContainers(Items2, DG2.ItemContainerGenerator);
var visibleitems1 = visiblerows1.Select(x => x.DataContext);
var visibleitems2 = visiblerows2.Select(x => x.DataContext);
var visibleconnectors = Connectors.Where(x => visibleitems1.Contains(x.Start) &&
visibleitems2.Contains(x.End));
VisibleConnectors.Where(x => !visibleconnectors.Contains(x))
.ToList()
.ForEach(x => VisibleConnectors.Remove(x));
visibleconnectors.Where(x => !VisibleConnectors.Contains(x))
.ToList()
.ForEach(x => VisibleConnectors.Add(x));
foreach(var connector in VisibleConnectors)
{
var startrow = visiblerows1.FirstOrDefault(x => x.DataContext == connector.Start);
var endrow = visiblerows2.FirstOrDefault(x => x.DataContext == connector.End);
if (startrow != null)
connector.StartPoint = Point.Add(startrow.TransformToAncestor(Root).Transform(new Point(0, 0)),
new Vector(startrow.ActualWidth + 5, (startrow.ActualHeight / 2)*-1));
if (endrow != null)
connector.EndPoint = Point.Add(endrow.TransformToAncestor(Root).Transform(new Point(0, 0)),
new Vector(-5,(endrow.ActualHeight / 2 ) * -1));
}
}
private static List GetVisibleContainers(IEnumerable
Connector:
public class DataItemConnector: PropertyChangedBase
{
public object Start { get; set; }
public object End { get; set; }
private Point _startPoint;
public Point StartPoint
{
get { return _startPoint; }
set
{
_startPoint = value;
OnPropertyChanged("StartPoint");
}
}
private Point _endPoint;
public Point EndPoint
{
get { return _endPoint; }
set
{
_endPoint = value;
OnPropertyChanged("EndPoint");
}
}
}
Base class to support two way binding:
public class PropertyChangedBase:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
Application.Current.Dispatcher.BeginInvoke((Action) (() =>
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}));
}
}
Result:
INotifyPropertyChanged
.File -> New Project -> WPF Application
and see the results for yourself.