我想创建一个带有两列(X和Y)的 DataGrid ,每个列都可以填充不同的集合。
Y列始终使用 ObservableCollection(NPoint)中的Y数据填充,其中 NPoint 是具有X和Y属性的类。
X列开始填充"默认"其他地方定义的值( ObservableCollection(double))。这个"默认"集合属于单例类。但是,根据附近 CheckBox 的.IsChecked
,可能会使用与Y数据相同的集合中的X数据填充X列。
后一种情况很简单,因为两列都将共享相同的ItemsSource。但是,如何将 DataGrid 的一列绑定到一个对象,将另一列绑定到另一个对象?有没有办法将DataGrid.ItemsSource
绑定到两个不同的集合?是否可以使用多或 PriorityBinding 来完成?
答案 0 :(得分:2)
简而言之,这在DataGrid上是不可行的,它只能绑定到单个数据源。
请在此处查看同样的问题和建议: Bind a WPF data grid to multiple data sources
答案 1 :(得分:0)
在阅读@ techhero的回答之后,我有一个疯狂的想法,我设法完成了(感谢Tao Ling's answer to this question)。它并不完美,但它可以解决问题。我基本上将 DataGrid 分成两个,一个是X列(变量.ItemsSource
),一个是Y列,一个紧挨着另一个。
以下是相关代码:
<强> XAML 强>
<DataGrid Grid.Column="0"
x:Name="CoordinatesX"
LoadingRow="RowIndexX"
VerticalScrollBarVisibility="Disabled"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="X" x:Name="XColumn"/>
</DataGrid.Columns>
</DataGrid>
<DataGrid Grid.Column="1"
x:Name="CoordinatesY"
ItemsSource="{Binding DataContext.Points, ElementName=CableTab}"
LoadingRow="RowIndexY"
RowHeaderWidth="0"
ScrollViewer.ScrollChanged="ScrollChanged"
VerticalScrollBarVisibility="Visible"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Y"/>
</DataGrid.Columns>
</DataGrid>
<强> .CS 强>
private void RowIndexX(object sender, DataGridRowEventArgs e)
{
e.Row.Header = (e.Row.GetIndex() + 1).ToString();
}
private void RowIndexY(object sender, DataGridRowEventArgs e)
{
e.Row.Header = " ";
}
void ControlBindings()
{
var resultSections = NProjectProperties.Instance.ResultSections;
var cable = DataContext as NCable;
Binding binding;
if (EqualToResults.IsChecked == true)
{
CoordinatesX.ItemsSource = resultSections;
XColumn.IsReadOnly = true;
XColumn.Foreground = Brushes.DarkGray;
binding = new Binding();
}
else
{
CoordinatesX.ItemsSource = cable.Points;
XColumn.IsReadOnly = false;
XColumn.Foreground = Brushes.Black;
binding = new Binding("X");
}
binding.ValidatesOnDataErrors = true;
binding.NotifyOnValidationError = true;
XColumn.Binding = binding;
}
private void EqualToResultsChanged(object sender, RoutedEventArgs e)
{
ControlBindings();
}
private void ScrollChanged(object sender, ScrollChangedEventArgs e)
{
var scroll1 = NU.GetDescendantByType(CoordinatesX, typeof(ScrollViewer)) as ScrollViewer;
var scroll2 = NU.GetDescendantByType(CoordinatesY, typeof(ScrollViewer)) as ScrollViewer;
scroll1.ScrollToVerticalOffset(scroll2.VerticalOffset);
}
public static class NU
{
public static Visual GetDescendantByType(Visual element, Type type)
{
if (element == null) return null;
if (element.GetType() == type) return element;
Visual foundElement = null;
if (element is FrameworkElement)
{
(element as FrameworkElement).ApplyTemplate();
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
Visual visual = VisualTreeHelper.GetChild(element, i) as Visual;
foundElement = GetDescendantByType(visual, type);
if (foundElement != null)
break;
}
return foundElement;
}
}
ScrollViewer.ScrollChanged="ScrollChanged"
行允许 DataGrids 一起滚动。
但是,第一个 DataGrid 有一个行标题,由于某种原因使行略大。这意味着,如果第二个没有给出标题,它们就不会对齐。因此,第二个 DataGrid 被赋予一个LoadingRowY函数,该函数返回一个自“RowHeaderWidth="0"
以来不出现的”“标题。但是,这会使行以与第一个 DataGrid 相同的比例绘制,对齐它们。
可以看出,两个 DataGrids 之间的空间不是很好,干净,应该改进,但我现在很满意。