WPF DataGrid:将集合属性绑定到列
我有一门课叫Person:WPF DataGrid:将集合属性绑定到列,wpf,collections,binding,datagrid,Wpf,Collections,Binding,Datagrid,我有一门课叫Person: public class Person { private string _Name; private ObservableCollection<Smartphone> _Smartphones; // Properties } public class Smartphone { private string _Manufacturer; private bool _IsWorking; // Properties
public class Person
{
private string _Name;
private ObservableCollection<Smartphone> _Smartphones;
// Properties
}
public class Smartphone
{
private string _Manufacturer;
private bool _IsWorking;
// Properties
}
公共类人物
{
私有字符串\u名称;
私人可观测收集"智能手机;;
//性质
}
公共级智能手机
{
私人字符串制造商;
私人厕所正在工作;
//性质
}
在我看来,我有一个数据网格。
我的问题是:
有没有办法让我的DataGrid看起来像这样:
所有人在他们的收藏中都有相同的智能手机,但“正在工作”的价值观不同
编辑:
我在DataGrid中尝试了DataGrid,如:
<DataGrid ItemsSource="{Binding PersonCollection}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name" />
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Smartphones}">
</DataGrid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
但这不是我想要的“解决方案”
编辑2:如果有一个复选框而不是“真/假”,那就太好了。试试这个
SmartPhone.cs Person.cs
视图模型
公共类视图模型
{
公共视图模型()
{
ColumnHeaders=新的ObservableCollection();
PersonCollection=新的ObservableCollection()
{
new Person(){Name=“Foo”,
智能手机=新的ObservableCollection()
{new SmartPhone(){Manufacturer=“Manufacturer1”,IsWorking=true}
,新智能手机(){Manufacturer=“Manufacturer2”,IsWorking=false}
,new Person(){Name=“Bar”,
智能手机=新的ObservableCollection()
{new SmartPhone(){Manufacturer=“Manufacturer1”,IsWorking=true}
,新智能手机(){Manufacturer=“Manufacturer2”,IsWorking=false}
,新智能手机(){Manufacturer=“Manufacturer3”,IsWorking=true}}
,new Person(){Name=“FooBar”,
智能手机=新的ObservableCollection()
{new SmartPhone(){Manufacturer=“Manufacturer1”,IsWorking=true}
,新智能手机(){Manufacturer=“Manufacturer2”,IsWorking=false}
,新智能手机(){Manufacturer=“Manufacturer3”,IsWorking=true}
,新智能手机(){Manufacturer=“Manufacturer4”,IsWorking=false}
,新智能手机(){Manufacturer=“Manufacturer5”,IsWorking=true}
}}
};
foreach(PersonCollection.SelectMany(s=>s.smartners.Select)(s=>s.Manufacturer.Distinct())中的var项)
{
列标题。添加(项);
}
}
公共ObservableCollection PersonCollection{get;set;}
公共ObservableCollection列标题{get;set;}
}
输出
我希望这会有所帮助
好问题。如果您也发布您的尝试会更好。我想这可以通过
DataTable
轻松完成。您只需将列表
转换为带有必要列的datatable。另一种方法是CustomTypeDescriptor
(虽然不确定)。我想OP需要它在长度上是动态的,那么我想我误解了这个问题。我不确定,让OP确认一下。否则,这是一个很好的答案。每个皮尔逊会有相同数量的手机吗?这仍然是一个有效的解决方案吗?
public class Person
{
public string Name { get; set; }
public ObservableCollection<SmartPhone> SmartPhones { get; set; }
}
public class SmartPhone
{
public string Manufacturer { get; set; }
public bool IsWorking { get; set; }
}
public class MyDataGrid:DataGrid
{
public ObservableCollection<string> ColumnHeaders
{
get { return GetValue(ColumnHeadersProperty) as ObservableCollection<string>; }
set { SetValue(ColumnHeadersProperty, value); }
}
public static readOnly DependencyProperty ColumnHeadersProperty = DependencyProperty.Register("ColumnHeaders", typeof(ObservableCollection<string>), typeof(MyDataGrid), new PropertyMetadata(new PropertyChangedCallback(OnColumnsChanged)));
static void OnColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var dataGrid=d as MyDataGrid;
dataGrid.Columns.Clear();
//Add Person Column
dataGrid.Columns.Add(new DataGridTextColumn() { Header = "Name", Binding = new Binding("Name") });
//Add Manufactures Columns
foreach (var value in dataGrid.ColumnHeaders)
{
var column=new DataGridCheckBoxColumn(){Header=value,Binding=new Binding("SmartPhones"){ConverterParameter=value,Converter=new ManufacturerConverter()}};
dataGrid.Columns.Add(column);
}
}
}
public class ManufacturerConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var smartPhones = value as IEnumerable<SmartPhone>;
if (smartPhones != null && parameter!=null)
{
var phone=smartPhones.FirstOrDefault(s => s.Manufacturer == parameter.ToString());
if (phone != null)
return phone.IsWorking;
return false;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<StackPanel>
<local:MyDataGrid AutoGenerateColumns="False"
ColumnHeaders="{Binding ColumnHeaders}"
ItemsSource="{Binding PersonCollection}"
CanUserAddRows="False" IsReadOnly="True">
</local:MyDataGrid>
</StackPanel>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
public class ViewModel
{
public ViewModel()
{
ColumnHeaders = new ObservableCollection<string>();
PersonCollection = new ObservableCollection<Person>()
{
new Person(){Name="Foo",
SmartPhones=new ObservableCollection<SmartPhone>()
{new SmartPhone(){Manufacturer="Manufacturer1",IsWorking=true}
,new SmartPhone(){Manufacturer="Manufacturer2",IsWorking=false}}}
, new Person(){Name="Bar",
SmartPhones=new ObservableCollection<SmartPhone>()
{new SmartPhone(){Manufacturer="Manufacturer1",IsWorking=true}
,new SmartPhone(){Manufacturer="Manufacturer2",IsWorking=false}
,new SmartPhone(){Manufacturer="Manufacturer3",IsWorking=true}}}
, new Person(){Name="FooBar",
SmartPhones=new ObservableCollection<SmartPhone>()
{new SmartPhone(){Manufacturer="Manufacturer1",IsWorking=true}
,new SmartPhone(){Manufacturer="Manufacturer2",IsWorking=false}
,new SmartPhone(){Manufacturer="Manufacturer3",IsWorking=true}
,new SmartPhone(){Manufacturer="Manufacturer4",IsWorking=false}
,new SmartPhone(){Manufacturer="Manufacturer5",IsWorking=true}
}}
};
foreach (var item in PersonCollection.SelectMany(s=>s.SmartPhones).Select(s=>s.Manufacturer).Distinct())
{
ColumnHeaders.Add(item);
}
}
public ObservableCollection<Person> PersonCollection { get; set; }
public ObservableCollection<string> ColumnHeaders { get; set; }
}