[英]Binding List<List<object>> to DataGrid columns in code-behind
I have a problem binding List<List> to DataGrid columns in code-behind.我在将 List<List> 绑定到代码隐藏中的 DataGrid 列时遇到问题。 Here is my list of lists:这是我的清单:
private List<List<object>> matrix = new List<List<object>>()
{
new List<object>(){53, 2500, 3000, 3500, 4000, 4500, 5000},
new List<object>(){2500, 1, 0, 0, 0, 0, 0},
new List<object>(){3000, 0, 1, 0, 0, 0, 0},
new List<object>(){3500, 0, 0, 1, 0, 0, 0},
new List<object>(){4000, 0, 0, 0},
new List<object>(){4500, 0, 0, 0, 0, 1, 0},
new List<object>(){5000, 9, 7, 5, 4, 1, 1},
new List<object>(){1, 0, 0, 0, 0, 0, 0},
new List<object>(){2, 0, 0, 0, 0, 0, 0},
new List<object>(){0, 0, 0, 0, 0, 0, 0}
};
public List<List<object>> Matrix
{
get { return matrix; }
set
{
matrix = value;
OnPropertyChanged(nameof(Matrix));
}
I've done this in XAML like this:我在 XAML 中这样做是这样的:
<DataGrid ItemsSource="{Binding Matrix}" VerticalAlignment="Top" FontSize="14" x:Name="matrixDataGrid" Height="420" Width="630" MinRowHeight="20" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=[0], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[1], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[2], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[3], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[4], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[5], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[6], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[7], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[8], Mode=TwoWay}"/>
<DataGridTextColumn Binding="{Binding Path=[9], Mode=TwoWay}"/>
</DataGrid.Columns>
</DataGrid>
And here is the result: the result of XAML binding这是结果: XAML 绑定的结果
And I would call it half-working.我会称之为半工作。 The first problem is an extra row and 3 extra columns.第一个问题是一个额外的行和 3 个额外的列。 The second one is that I will have a lot of work if I would like to have 1000 columns.第二个是如果我想要 1000 列,我将有很多工作要做。 Also, there are a lot of XAML binding errors: Binding errors .还有很多 XAML binding errors: Binding errors 。 And I don't even know how this specific binding works, and it looks strange.而且我什至不知道这个特定的绑定是如何工作的,看起来很奇怪。 I would be glad for the explanation.我会很高兴的解释。
My unsuccessful attempts to do this in code-behind look like this:我在代码隐藏中尝试执行此操作的失败尝试如下所示:
Binding binding = new Binding();
binding.Source = Matrix;
binding.Path = new PropertyPath("[0]");
binding.Mode = BindingMode.TwoWay;
columnOne.Binding = binding;
XAML file at the moment: XAML 目前档案:
<DataGrid ItemsSource="{Binding Matrix}" VerticalAlignment="Top" FontSize="14" x:Name="matrixDataGrid" Height="420" Width="630" MinRowHeight="20" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Width="50" x:Name="columnOne" />
</DataGrid.Columns>
</DataGrid>
I only get empty column: result of attempt .我只得到空列: result of attempt 。 I've seen someone doing this with DataTable, but I would like to do this the way I want if it is possible.我见过有人用 DataTable 这样做,但如果可能的话,我想按照我想要的方式来做。
I wouldn't mess with a DataGrid
, it's just too much hassle unless you need specific features of the DataGrid
like sortable headers, grouping, etc. DataGrid
also will not handle a huge matrix very well, since each cell is pretty heavy UI wise.我不会弄乱DataGrid
,这太麻烦了,除非您需要DataGrid
的特定功能,如可排序的标题、分组等DataGrid
也不能很好地处理巨大的矩阵,因为每个单元格在 UI 方面都非常笨重。
Instead, Since you have a List
of List
s, you can do the same thing with an ItemsControl
of ItemsControl
s.相反,由于您有一个List
的List
,您可以使用ItemsControl
的ItemsControl
做同样的事情。 As long as each element has the same height/width, then it would come out looking just like the DataGrid
.只要每个元素具有相同的高度/宽度,那么它看起来就像DataGrid
一样。 You could do that by fixing the size of each element, or set the ItemsPanel
to something that enforces consistent sizing (like UniformGrid
).您可以通过固定每个元素的大小来做到这一点,或者将ItemsPanel
设置为强制大小一致的东西(如UniformGrid
)。
To make binding work so the cells are editable, you need to wrap the value in each matrix cell in something that implements INotifyPropertyChanged.要使绑定起作用以便单元格可编辑,您需要将每个矩阵单元格中的值包装在实现 INotifyPropertyChanged 的内容中。
public class ItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string p = null)
=> PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(p));
private int _value;
public int Value
{
get => _value;
set
{
_value = value;
OnPropertyChanged();
}
}
public static implicit operator int(Item i) => i.Value;
public static implicit operator Item(int i) => new () { Value = i};
public static int[] GetArray(IEnumerable<Item> input)
=> input.Select(i => i.Value).ToArray();
public static int[][] GetMatrix(IEnumerable<IEnumerable<Item>> input)
=> input.Select(ToArray).ToArray();
}
Here's the XAML for a MatrixGrid, derived from ItemsControl.这是从 ItemsControl 派生的 MatrixGrid 的 XAML。 The code behind doesn't have anything in it but the autogenerated constructor.除了自动生成的构造函数之外,后面的代码没有任何内容。
<ItemsControl x:Class="WpfApp1.MatrixGrid" x:Name="ic"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding ElementName=ic, Path=ItemsSource.Count}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
TextAlignment="Center"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Demo:演示:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1">
<local:MatrixGrid x:Name="matrixGrid"/>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
matrixGrid.ItemsSource = Matrix;
}
public List<List<ItemViewModel>> Matrix { get; } = new List<List<Item>>()
{
new (){53, 2500, 3000, 3500, 4000, 4500, 5000},
new (){2500, 1, 0, 0, 0, 0, 0},
new (){3000, 0, 1, 0, 0, 0, 0},
new (){3500, 0, 0, 1, 0, 0, 0},
new (){4000, 0, 0, 0},
new (){4500, 0, 0, 0, 0, 1, 0},
new (){5000, 9, 7, 5, 4, 1, 1},
new (){1, 0, 0, 0, 0, 0, 0},
new (){2, 0, 0, 0, 0, 0, 0},
new (){0, 0, 0, 0, 0, 0, 0}
};
}
Nice thing about this is that there's no need for code behind or generating bindings programmatically.这样做的好处是不需要隐藏代码或以编程方式生成绑定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.