I'm surprised that you didn't get any answers to your question. Maybe it's because you don't seem to be doing things the WPF way, or maybe because you're asking for so much?
First things first... you need to create a data type class that implements the INotifyPropertyChanged
interface and contains all of the properties required for display in each row of the ListView
. In your case, you need three collections and three selected item values. As an example, you could do something like this (implementing the INotifyPropertyChanged
interface yourself):
public class RowData : INotifyPropertyChanged
{
public ObservableCollection<Employee> Employees { get; set; }
public Employee SelectedEmployee { get; set; }
public ObservableCollection<Product> Products { get; set; }
public Product SelectedProduct { get; set; }
public ObservableCollection<Brush> Colours { get; set; }
public Brush SelectedColour { get; set; }
}
Note the use of the Brush
class rather than the Color
struct, this is because Brush
is a class, which means that we can bind to it and also because it is more predominantly used in WPF.
However, it is not optimal having the same collections in every object in every row, except for the Colours
collection, which could be different for each row. Having said that, that is exactly what I'm going to do because it will be quicker for me to explain and you can improve your code yourself at a later stage:
So now you have your data type class, we need to add a property of that type to bind to your ListView
control. If you are using the code behind of your MainWindow
, then let's create a DependencyProperty
for it:
public static readonly DependencyProperty RowDataProperty = DependencyProperty.
Register("RowData", typeof(ObservableCollection<RowData>), typeof(MainWindow),
new UIPropertyMetadata(new ObservableCollection<RowData>()));
public ObservableCollection<RowData> RowData
{
get { return (ObservableCollection<RowData>)GetValue(RowDataProperty); }
set { SetValue(RowDataProperty, value); }
}
After filling your collection, you can now bind it to the ListView
control:
xmlns:Local="clr-namespace:YourWpfApplicationName"
...
<ListView ItemsSource="{Binding RowData, RelativeSource={RelativeSource AncestorType={
x:Type Local:MainWindow}}}">
...
</ListView>
In short, the RelativeSource Binding
is simply looking for the property you defined in the code behind. Now, how to define that a ComboBox
should appear in each GridViewColumn
? You need to define the GridViewColumn.CellTemplate
:
<GridViewColumn Header="Employees">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Employees}" SelectedItem="{Binding
SelectedEmployee}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
You'll need to define the other columns from this example. So the final part of this puzzle is how to update the content of the Colours
ComboBox
dependent on the selected values of the other ComboBox
es? The answer lies in your selected value properties in your RowData
class:
public Employee SelectedEmployee
{
get { return selectedEmployee; }
set
{
selectedEmployee = value;
NotifyPropertyChanged(SelectedEmployee);
Colours = GetColours();
}
}
private ObservableCollection<Brush> GetColours()
{
ObservableCollection<Brush> newColours = new ObservableCollection<Brush>();
if (SelectedEmployee.Name == "Some Name" && SelectedProduct.Name ==
"Some Product") newColours.AddRange( new List<Brush>() { Brushes.Red,
Brushes.White, Brushes.Blue } );
else ...
}
There are many ways to do this and I'll leave that up to you. You should now have a working example and I now realise why nobody had answered your question... far too much for anyone sane to type! After spending so long on this, I would appreciate it if you try to solve any minor problems you find with this on your own and hope it helps you.