Reputation: 1244
The problem is that I’m changing the collection of items at runtime and I can’t get the combobox to update to show the new items. I’d like to achieve this via xaml.
I’d like to solve this for a single combobox, and then also for a datagrid either as either a datagridComboBoxColumn or as a templatecolumn containing a combobox as the datatemplate.
I’ve got code like:
public class Member
{
public string PublicID {get; set;}
public string Description {get; set;}
}
public ObservableCollection<Member> ComboBoxSource;
public UpdateComboBoxContents()
{
List<Member> newList;
// Omitted Code to retrieve list from datasource..
ComboBoxSource = new ObservableCollection<Member>(newList);
// If I uncomment the next line, combobox will show new contents:
//myComboBox.itemssource = ComboBoxSource;
// I’ve also tried..
OnPropertyChanged("ComboBoxListSource");
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string Name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(Name));
}
}
Where:
public partial class MyForm: UserControl, INotifyPropertyChanged
Combobox xaml looks like:
<ComboBox Name="myComboBox" SelectedValuePath="PublicID"
DisplayMemberPath="Description" ItemsSource="{Binding ComboBoxListSource,
UpdateSourceTrigger=PropertyChanged}"/>
I figure I’m screwing up binding or implementing INotifyPropertyChanged. In debug I noticed that the handler is always null so the event isn’t raised.
For the second part of this question (implementing into a datagrid) I’ve got:
public observableCollection<DatarowWithMember> ListDataRowWithMember;
// Code to populate list..
myDataGrid.Itemsource = ListDataRowWithMember
where DataRowWithMember is a class that implements INotifyPropertyChanged and has a MemberID property which should point to Member’s PublicID
I’ve tried this xaml:
<DataGridTemplateColumn Header="Group" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding ComboBoxListSource,
RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedValue="{Binding MemberID, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Description"
SelectedValuePath="PublicID"
IsHitTestVisible="False" SelectionChanged="ComboBoxChanged">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding ComboBoxListSource,
RelativeSource={RelativeSource AncestorType=UserControl}}"
DisplayMemberPath="Description" SelectedValuePath="PublicID"
SelectedValue="{Binding MemberID,
UpdateSourceTrigger=PropertyChanged}"
SelectionChanged="ComboBoxChanged"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
Solution: As others pointed out, I had a typo with ComboBoxSource and ComboBoxListSource - this wasn't a problem in code but my error in writing out this question.
Checking output window did indeed show binding problems namely that property ComboBoxSource could not be found. I changed to:
private ObservableCollection<Member> _ComboBoxSource = new ObservableCollection<Member>()
public ObservableCollection<Member> ComboBoxSource
{
get { return _ComboBoxSource; }
}
and that worked. class Properties vs members ?
Upvotes: 0
Views: 3278
Reputation: 1486
You have two problems in UpdateComboBoxContent
that cause that.
First, your property is called ComboBoxSource
, while in the method, you call property changed with "ComboBox List Source".
Second, you don't need to override the ObservableCollection
at all. ObservableCollection
can notify the binding by itself. Instead of overriding it, call ComboBoxSource.Clear()
and then populate it with the new data, if you can't update only the changed items.
Also, never set myComboBox.itemssource = ComboBoxSource;
you break your binding by doing so. If you want to bind properties using code behind, see: http://msdn.microsoft.com/en-us/library/ms742863.aspx
Upvotes: 1
Reputation: 883
From what it seems you are mixing up the property name ComboBoxSource and the PropertyCHanged event parameter together with the binding. You should use the same name like ComboBoxSource in all places like this:
public ObservableCollection<Member> ComboBoxSource;
public UpdateComboBoxContents()
{
List<Member> newList;
// Omitted Code to retrieve list from datasource..
ComboBoxSource = new ObservableCollection<Member>(newList);
// I’ve also tried..
OnPropertyChanged("ComboBoxSource");
}
<ComboBox Name="myComboBox" SelectedValuePath="PublicID"
DisplayMemberPath="Description" ItemsSource="{Binding ComboBoxSource,
UpdateSourceTrigger=PropertyChanged}"/>
Upvotes: 0