我在窗口窗体上有两个网格,当用户单击第一个网格单元格时,我需要通过单元格之间的线从一个网格到另一个网格显示映射,并且此功能适用于滚动条,这意味着行位置将根据单元格位置而改变当用户移动垂直滚动条时。
请使用下面的链接查看图像以获得更多说明。
http://s8.postimg.org/49s7i2lvp/Mapping.png
感谢您提供任何帮助,并在此先感谢您
向Shailesh 致以最诚挚的
问候
我在窗口窗体上有两个网格,当用户单击第一个网格单元格时,我需要通过单元格之间的线从一个网格到另一个网格显示映射,并且此功能适用于滚动条,这意味着行位置将根据单元格位置而改变当用户移动垂直滚动条时。
请使用下面的链接查看图像以获得更多说明。
http://s8.postimg.org/49s7i2lvp/Mapping.png
感谢您提供任何帮助,并在此先感谢您
向Shailesh 致以最诚挚的
问候
好的。我将其发布为答案,因为 OP 要求它。
这是我的 WPF 对此的看法:
<Window x:Class="MiscSamples.DataGridConnectors"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataGridConnectors" Height="300" Width="300">
<Grid x:Name="Root">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ItemsControl ItemsSource="{Binding VisibleConnectors}" Grid.ColumnSpan="3">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line X1="{Binding StartPoint.X}"
Y1="{Binding StartPoint.Y}"
X2="{Binding EndPoint.X}"
Y2="{Binding EndPoint.Y}"
Stroke="Black"
StrokeThickness="2"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<DataGrid ItemsSource="{Binding Items1}" x:Name="DG1" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=.}"/>
</DataGrid.Columns>
</DataGrid>
<DataGrid ItemsSource="{Binding Items2}" x:Name="DG2" AutoGenerateColumns="False" Grid.Column="2">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=.}"/>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Column="1">
<Button Content="Sequential" Click="Sequential_Click"/>
<Button Content="Random" Click="Random_Click"/>
</StackPanel>
</Grid>
</Window>
代码背后:
public partial class DataGridConnectors : Window
{
public List<string> Items1 { get; set; }
public List<string> Items2 { get; set; }
public List<DataItemConnector> Connectors { get; set; }
private ObservableCollection<DataItemConnector> _visibleConnectors;
public ObservableCollection<DataItemConnector> VisibleConnectors
{
get { return _visibleConnectors ?? (_visibleConnectors = new ObservableCollection<DataItemConnector>()); }
}
public DataGridConnectors()
{
Connectors = new List<DataItemConnector>();
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<ScrollViewer>(DG1).FirstOrDefault();
var scrollviewer2 = FindDescendent<ScrollViewer>(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<FrameworkElement> GetVisibleContainers(IEnumerable<object> source, ItemContainerGenerator generator)
{
return source.Select(generator.ContainerFromItem).Where(x => x != null).OfType<FrameworkElement>().ToList();
}
public static List<T> FindDescendent<T>(DependencyObject element) where T : DependencyObject
{
var f = new List<T>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var child = VisualTreeHelper.GetChild(element, i);
if (child is T)
f.Add((T)child);
f.AddRange(FindDescendent<T>(child));
}
return f;
}
private void Sequential_Click(object sender, RoutedEventArgs e)
{
Connectors.Clear();
Enumerable.Range(0, 1000).Select(x => new DataItemConnector() { Start = Items1[x], End = Items2[x] })
.ToList()
.ForEach(x => Connectors.Add(x));
scrollviewer_ScrollChanged(null, null);
}
private void Random_Click(object sender, RoutedEventArgs e)
{
Connectors.Clear();
var random = new Random();
Enumerable.Range(500, random.Next(600, 1000))
.Select(x => new DataItemConnector()
{
Start = Items1[random.Next(0, 999)],
End = Items2[random.Next(0, 999)]
})
.ToList()
.ForEach(Connectors.Add);
scrollviewer_ScrollChanged(null, null);
}
}
连接器:
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");
}
}
}
支持两种方式绑定的基类:
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));
}));
}
}
结果:
INotifyPropertyChanged
.File -> New Project -> WPF Application
,然后自己查看结果。就像是 :
foreach (DataGridViewRow row in dataGrid.Rows)
{
var cellValue = row.Cells["field"].Value;
if (cellValue != null && cellValue.ToString() == "something")
{
dataGrid.Rows[row.Index].Selected = true;
try
{
dataGrid.FirstDisplayedScrollingRowIndex = row.Index - 4;
}
catch (Exception execc)
{
dataGrid.FirstDisplayedScrollingRowIndex = row.Index;
}
}
}
这个?
然后对我想的另一个网格使用相同的