I've a problem with the WPF datagrid. I have two ComboBox columns and the second one should set it's datacontext dependant of what is selected in the first one.
ViewModel
public class MyCollection: AbstractViewModel
{
private BindingList<string> _subitems;
public BindingList<string> Subitems
{
get { return _subitems; }
set { _subitems = value; Notify("Subitems");}
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; Notify("Name");}
}
}
Xaml
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedName}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValuePath="Name"
x:Name="CollectionBox"
SelectedValue="{Binding SelectedName}"
DisplayMemberPath="Name"
ItemsSource="{Binding SomeBinding}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedSubitem}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding SelectedSubitem}"
ItemsSource="{Binding ElementName=CollectionBox, Path=SelectedItem.Subitems}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
The binding for my first ComboBox is ok but I did not see any items in my second ComboBox (the viewmodel has entries for booth of the ComboBoxes); only the TextBox binding works as expected. I tryed it with a ComboBoxColumn as well but with the same result.
here an simple working example how you could use your ViewModel to achieve your needs
XAML
<DataGrid ItemsSource="{Binding Source}" Width="500">
<DataGrid.Columns>
<DataGridTemplateColumn Header="main" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedName}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValuePath="Name"
SelectedValue="{Binding SelectedName}"
SelectedItem="{Binding SelectedMainItem, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name"
ItemsSource="{Binding SomeBinding}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="sub" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding SelectedSubitem}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding SelectedSubitem}"
ItemsSource="{Binding Path=SelectedMainItem.Subitems}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new VMColl();
}
}
public class VMColl
{
List<VM> source;
public List<VM> Source
{
get { return source; }
set { source = value; }
}
public VMColl()
{
source = new List<VM>(){new VM(),new VM(),new VM(),new VM()};
}
}
/// <summary>
/// your Row
/// </summary>
public class VM : Notify
{
private List<mainObj> _items;
public List<mainObj> SomeBinding
{
get { return _items; }
set
{
_items = value;
OnPropertyChanged("Items");
}
}
private string _selectedName;
public string SelectedName
{
get { return _selectedName; }
set
{
_selectedName = value;
OnPropertyChanged("SelectedName");
}
}
private mainObj _selectedMainItem;
public mainObj SelectedMainItem
{
get { return _selectedMainItem; }
set
{
_selectedMainItem = value;
OnPropertyChanged("SelectedMainItem");
OnPropertyChanged("SelectedMainItem.Subitems");
}
}
private string _selectedSubitem;
public string SelectedSubitem
{
get { return _selectedSubitem; }
set
{
_selectedSubitem = value;
OnPropertyChanged("SelectedSubitem");
}
}
public VM()
{
SomeBinding = new List<mainObj>() {new mainObj("first"),new mainObj("second"),new mainObj("someother") };
}
}
public class mainObj : Notify
{
private BindingList<string> _subitems;
public BindingList<string> Subitems
{
get { return _subitems; }
set
{
_subitems = value;
OnPropertyChanged("Subitems");
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public mainObj(string name)
{
_name = name;
_subitems = new BindingList<string>(){"1","2","3"};
}
}
public class Notify : INotifyPropertyChanged
{
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}