我正在编写C#WPF应用程序,用户可以在其中将测试架中的样品条形码条形码到该应用程序中。
机架由行组成。每行包含许多样本。
每个样本都可以具有样本详细信息的列表(用户每次进行更改时的标识符和日期时间)。
这里有一张图片可以更好地形象化:Picture of Rack
我想在DataGrid中表示它,用户可以在其中编辑网格中的每个样本。
我发现XAML相当困难。我已经成功使用代码隐藏实现了我想要的(见下文),但是我想在XAML中做到这一点。这是picture of output。
这可能吗?
谢谢
附加信息:
RackPosition
类的Row
属性ColumnPosition
类的Sample
History[0].Identifier
我的代码:
班级:
public class Rack
{
public string Name { get; set; }
public DateTime DateCreated { get; set; }
public List<Row> Rows { get; set; } = new List <Row>();
}
public class Row
{
public int RackPosition { get; set; }
public string Name { get; set; }
public List<Sample> Samples { get; set; } = new List <Sample>();
}
public class Sample
{
public int ColumnPosition { get; set; }
public List<SampleDetails> History { get; set; } = new List <SampleDetails>();
}
public class SampleDetails
{
public string Identifier { get; set; }
public DateTime TimeStamp { get; set; }
}
Datagrid:
<DataGrid x:Name="MainDG" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.RowHeaderStyle>
<Style TargetType="{x:Type DataGridRowHeader}">
<Setter Property="Content" Value="{Binding RackPosition}"/>
</Style>
</DataGrid.RowHeaderStyle>
</DataGrid>
后面的代码:
public Rack CurrentRack { get; set; }
public MainWindow()
{
InitializeComponent();
SetupDataGrid();
}
//Gets a dummy rack
public Rack GetExampleRack()
{
Rack rack = new Rack();
for (int i = 0; i < 4; i++)
{
Row row = new Row();
row.Samples = new List<Sample>();
row.RackPosition = i;
for (int j = 0; j < 5; j++)
{
row.Samples.Add(new Sample { ColumnPosition = j });
}
rack.Rows.Add(row);
}
SampleDetails testSample1 = new SampleDetails { Identifier = "Test ID 1", TimeStamp = DateTime.Now };
SampleDetails testSample2 = new SampleDetails { Identifier = "Test ID 2", TimeStamp = DateTime.Now };
rack.Rows[0].Samples[0].History.Add(testSample1);
rack.Rows[1].Samples[3].History.Add(testSample2);
return rack;
}
private void SetupDataGrid()
{
MainDG.Columns.Clear();
CurrentRack = GetExampleRack();
foreach (var sample in CurrentRack.Rows[0].Samples)
{
var sampleIndex = CurrentRack.Rows[0].Samples.IndexOf(sample);
DataGridTemplateColumn col = new DataGridTemplateColumn();
col.Header = sampleIndex;
FrameworkElementFactory textBox = new FrameworkElementFactory(typeof(TextBox));
var binding = new Binding();
binding.BindingGroupName = ".";
binding.Path = new PropertyPath($"Samples[{sampleIndex}].History[0].Identifier");
textBox.SetBinding(TextBox.TextProperty, binding);
DataTemplate dt = new DataTemplate { VisualTree = textBox };
dt.Seal();
col.CellTemplate = dt;
MainDG.Columns.Add(col);
}
MainDG.ItemsSource = CurrentRack.Rows;
}
[花了一些时间考虑一下这个问题之后,我认为在XAML中没有任何实用的方法可以做到这一点。我真的不认为DataGrid
旨在按您需要的方式处理动态列-至少不是通过数据绑定自动进行。我也不知道有其他控件可以完成这项工作。
即使接受您必须使用some后面的代码,我也无法挑选出可以轻松用XAML替换的代码的任何部分。
DataGrid
更好的方法了-即使您设计了一些可以在XAML中使用的组件,它最终还是会调用后台代码来完成此操作。Row.Samples
,但是由于您需要基于DataTemplate
动态绑定,因此您必须使用带有自定义sampleIndex
的类似MultiBinding
的东西。尽管这行得通,但我认为它最终只会使代码变得更复杂-仅保留它就更简单了。[我的另一个想法是完全放弃IMultiValueConverter
。我考虑使用DataGrid
,其中行的ItemsControl
包含另一个用于显示单元格的ItemTemplate
。然后,您可以将主ItemsControl
绑定到ItemsControl.ItemsSource
,将行级Rack.Rows
绑定到ItemsControl.ItemsSource
。这会自动为您创建所有单元格,但还会给您带来其他问题:
Row.Samples
之外创建。ItemsControl
与Grid
列一起使用来解决此问题,但是SharedSizeGroup
不支持来自Grid
的自动动态列,因此我们回到了从ItemsSource
开始的地方。 >清单继续,解决这些问题,您基本上将最终重新创建DataGrid
控件中已经存在的所有这些功能。
TL; DR:我认为没有更好的以XAML为中心的方法。