WPF MVVM DataGrid在运行时用查询填充



作为WPF和MVVM的新手,我在过去几天一直在努力解决这个问题。我已经搜索了整个stackoverflow和google/Youtube来寻求帮助。

我有一个数据网格(从OrderListView绑定),它是由一个模型的BindableCollection (Caliburn Micro)填充的。然而,我需要从另一个BindableCollection ProductList中引入一个属性('Program')的链接数据,(两个集合共享一个共同的属性'Code'。

基本上,我希望DataGrid显示所有基于OrderModel的列,并在运行时用来自Products集合的相关数据填充名为Programs的列。

OrderModel.cs

public class OrderModel : BaseModel
{
private DateTime _orderDate;
public DateTime OrderDate
{
get { return _orderDate; }
set { _orderDate = value; OnPropertyChanged(); }
}
private string _code;
public string Code
{
get { return _code; }
set { _code = value; OnPropertyChanged(); }
}
private int _qty;
public int Qty
{
get { return _qty; }
set { _qty = value; OnPropertyChanged(); }
}

ProductModel.cs

public class ProductModel : BaseModel
{
private string _code;
public string Code
{
get { return _code; }
set { _code = value; OnPropertyChanged(); }
}
private int _program;
public int Program
{
get { return _program; }
set { _program = value; OnPropertyChanged(); }
}

DataGrid在OrderView.xaml

<DataGrid ItemsSource="{Binding OrderListView}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Code}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Qty}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Program}"/>  <- This from ProductList ??
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

OrderViewModel.cs

public class OrderViewModel : Screen
{
private readonly IDataConnection _connect;
private ICollectionView _orderView;
public ICollectionView OrderListView
{
get => _orderView;
set
{
_orderView = value;
NotifyOfPropertyChange(() => OrderListView);
}
}
private BindableCollection<OrderModel> _orderList;
public BindableCollection<OrderModel> OrderList
{
get => _orderList;
set
{
_orderList = value;
NotifyOfPropertyChange(() => OrderList);
}
}
private BindableCollection<ProductModel> _productList;
public BindableCollection<ProductModel> ProductList
{
get { return _productList; }
set { _productList = value; }
}
private string _code;
public string Code
{
get { return _code; }
set { _code = value; NotifyOfPropertyChange(() => Code); }
}
private int _qty;
public int Qty
{
get { return _qty; }
set { _qty = value; NotifyOfPropertyChange(() => Qty); }
}
private int _program;
public int Program
{
get { return _program; }
set
{
_program = value;
NotifyOfPropertyChange(() => Program);
}
}
public OrderViewModel(IDataConnection connect)
{
DisplayName = "Orders";
var allOrders = await _connect.Orders_GetByDateRange(StartDate, EndDate);
OrderList = new BindableCollection<OrderModel>(allOrders);
OrderListView = CollectionViewSource.GetDefaultView(OrderList);
var allProducts = await _connect.Products_GetAll();
ProductList = new BindableCollection<ProductModel>(allProducts);
}
}

基本上'代码'在模型中匹配,我想把相关的程序拉到列中。

DataGrid绑定的ItemsSource需要包含列绑定的所有属性。

这意味着需要将Program属性添加到当前的OrderModel或创建包含这两个属性的新模型。

public class OrderModel : BaseModel
{
private DateTime _orderDate;
public DateTime OrderDate
{
get { return _orderDate; }
set { _orderDate = value; OnPropertyChanged(); }
}
private string _code;
public string Code
{
get { return _code; }
set { _code = value; OnPropertyChanged(); }
}
private int _qty;
public int Qty
{
get { return _qty; }
set { _qty = value; OnPropertyChanged(); }
}
private int _program;
public int Program
{
get { return _program; }
set { _program = value; OnPropertyChanged(); }
}
}

然后需要逻辑将新的Program值与其他集合中的值链接起来。

最干净的地方很可能是修改您的查询(假设您正在使用数据库连接)

最有可能的是在为订单做选择时包含一个JOIN

但是,在客户端执行此操作,这意味着在从IDataConnection接收到数据之后,将看起来像这样:

using System.Linq;
...
public OrderViewModel(IDataConnection connect)
{
DisplayName = "Orders";
var allOrders = await _connect.Orders_GetByDateRange(StartDate, EndDate);
var allProducts = await _connect.Products_GetAll();
ProductList = new BindableCollection<ProductModel>(allProducts);
foreach(var order in allOrders)
{
//assumes "Code" is unique within `ProductList`
order.Program = ProductList.Single(p => p.Code == order.Code);
}
OrderList = new BindableCollection<OrderModel>(allOrders);
OrderListView = CollectionViewSource.GetDefaultView(OrderList);
}

最新更新