我有2节课:
public class Order : ObservableCollection<string>
{
public Order()
{
Add("1st");
Add("2nd");
Add("3rd");
for (int i=4; i< 100; i++)
{
Add($"{i}th");
}
}
}
public class Id : ObservableCollection<string>
{
public Id()
{
Add("abc12345");
Add("dce12345");
//3000 id,...
}
}
在我的xaml中:
<DockPanel Grid.Row="2" Grid.Column="0" Height="Auto" Background="LightBlue">
<DockPanel.Resources>
<src:Order x:Key="order"/>
<src:Id x:Key="id"/>
</DockPanel.Resources>
<ListView ItemsSource="{StaticResource order}">
<ListView.View>
<GridView>
<GridViewColumn Header="Order"/>
<GridViewColumn Header="ID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox Width="200" ItemsSource="{StaticResource id}">
</ComboBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</DockPanel>
绑定得很好:列表框中“顺序”列(第 1 到第 99 列)的 100 行中的每一行都有一个可以选择 ID 的组合框。但是,我如何获取每行中的每个组合框选定的值,并将它们绑定到在
public partial class MainWindowViewModel : ObservableObject
而不是 MainWindow
中创建的值(或列表)?
我认为 LINQ 是可能的,但必须从 MainWindow
而不是 MainViewModel
调用。但这对我的控制来说毫无意义。感谢任何帮助。
从列表类型继承来表达一组数据是一个典型的初学者错误:
您有很多汽车品牌,因此将
Car
改为 List
。 (错误)Team
设为 List
。 (错误)Order
设为 List
。 (错误)
组合通常是比使用继承更好的选择。
大多数对象的关系都可以使用组合来正确表达(就像现实世界的对象一样)。
如果有帮助,您只需在要添加新功能时扩展列表类型。
例如,
TemporaryCollection
可以跟踪其项目的存储时间并在一定时间后删除它们。 ==>新功能==>扩展List
。List<int>
变为 IntegerList
。
在所有其他情况下,从列表类型扩展都是错误的。
您还可以使用语义来检查您是否正确应用了正确的类设计。
例如,订单不是多个产品。但一个订单有多种产品。
以及订单has一个ID和has一个时间戳和has一个关联的客户。
如果关系是 is a 那么你必须使用继承。 如果关系是 has a 那么你必须使用组合:
订单.cs
// If the class serves as a binding source and is a DependencyObject (for example a Control),
// it MUST implement its properties as dependency properties.
// If the class serves as a binding source is not a DependencyObject (for example a view model class),
// it MUST implement INotifyPropertyChanged.
class Order : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<string> Items { get; }
public int Id { get; }
private Order selectedOrderItem;
public Order SelectedOrderItem
{
get => this.selectedOrderItem;
set
{
this.selectedOrderItem = value;
OnPropertyChanged();
}
}
public Order(int id)
{
this.Id = id;
this.Items = new ObservableCollection<string>();
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
MainViewModel.cs
class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<Order> Orders { get; }
private Order selectedOrder;
public Order SelectedOrder
{
get => this.selectedOrder;
set
{
var oldSelectedOrder = this.selectedOrder;
this.selectedOrder = value;
OnPropertyChanged();
OnSelectedOrderChanged(oldSelectedOrder, value);
}
}
public MainViewModel()
{
this.Orders = new ObservableCollection<Order>();
for (int orderId = 1; orderId < 4; orderId++)
{
var newOrder = new Order(orderId);
for (int itemCount = 0; itemCount < 3; itemCount++)
{
string orderItem = $"Item {itemCount}";
newOrder.Items.Add(orderItem);
}
this.Orders.Add(newOrder);
}
}
private void OnSelectedOrderChanged(Order oldSelectedOrder, Order newSelectedOrder)
{
// TODO::Handle selected Order
var selectedOrderItem = newSelectedOrder.SelectedOrderItem;
var orderId = newSelectedOrder.Id;
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
现在订单有商品和ID:
var items = order.Items;
var orderId = order.Id;
MainWindow.xaml
<Window>
<Window.DataContext>
<MainViewModel />
</Window.DataContext>
<ListView ItemsSource="{Binding Orders}"
SelectedItem="{Binding SelectedOrder}">
<ListView.View>
<GridView>
<GridViewColumn Header="Order">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type local:Order}">
<ComboBox ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedOrderItem}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="ID"
DisplayMemberBinding="{Binding Id}" />
</GridView>
</ListView.View>
</ListView>
</Window>