I have a viewmodel which implement INotifyPropertyChanged
. On this viewModel is a property called SubGroupingView
. This property is bound to the selected item of a combo box. When i change the combo box, the source property is being updated fine, but when I change the source property or when the control is initialized, the combobox.selectedItem
is NOT reflecting what exists in the property.
<ComboBox Grid.Column="3" Grid.Row="1"
Margin="0,1,4,1"
SelectedItem="{Binding Path=SubGroupingView, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}"
ItemsSource="{Binding Columns}"
DisplayMemberPath="DisplayName">
The property raises the PropertyChanged
event and the TraceSource output shows me that the binding detected it and transferred the value, its just that the combobox isn't reflecting it. Any ideas would be most welcome!
EDIT:
output from the trace source is this:System.Windows.Data Warning: 91 : BindingExpression (hash=23631369): Got PropertyChanged event from ReportViewModel (hash=52844413)
System.Windows.Data Warning: 97 : BindingExpression (hash=23631369): GetValue at level 0 from ReportViewModel (hash=52844413) using RuntimePropertyInfo(SubGroupingView): DataColumnViewModel (hash=58231222)
System.Windows.Data Warning: 76 : BindingExpression (hash=23631369): TransferValue - got raw value DataColumnViewModel (hash=58231222)
System.Windows.Data Warning: 80 : BindingExpression (hash=23631369): TransferValue - implicit converter produced DataColumnViewModel (hash=58231222)
System.Windows.Data Warning: 85 : BindingExpression (hash=23631369): TransferValue - using final value DataColumnViewModel (hash=58231222)
Here is the code for the source property:
public class ReportViewModel : ViewModelBase, IReportTemplate
{
public DataColumnViewModel SubGroupingView
{
get
{
return GetViewModel(_report.SubGrouping);
}
set
{
if (_report.SubGrouping == value.ColumnName)
return;
_report.SubGrouping = value.ColumnName;
RefreshDataSeries();
base.OnPropertyChanged("SubGroupingView");
开发者_C百科 base.OnPropertyChanged("IsReady");
}
}
}
Note: ViewModelBase
implements INotifyPropertyChange
.
ANSWER
I overloaded the ==, != operators,GetHashCode()
, and Equals(object)
and now it is working nicely. Thanks for all of your help!The object returned from your SubGroupingView must be "equal" to one of the objects in the ComboBox.Items (which means it must be in your Columns collection). So if you perform an "a.Equals(b)", it would need to return true.
If they are functionally the same, but not returning true when compared then that's your problem. You would need to either return the same object, or override the Equals method (and potentially the == and != operators).
If this is your issue, it's the same problem as in this question.
Is IsSynchronizedWithCurrentItem
on your ComboBox
perhaps set to false
? You could try explicitly setting IsSynchronizedWithCurrentItem="True"
and see if that helps.
The @CodeNaked 's answer is right. But in my case just overriding Object.Equals throws StackOverflowException. I think the whole answer is to implement full IEquatable that means implementing its Equals method and overriding Object.Equals(Object) and Object.GetHashCode methods as in this example (see the end of "Remarks" section - "Notes to Implementers" - and "Examples" section).
As my experience, You need set the SelectedItem by searching from ItemsSource.
For MVCC example, If you created a combobox with
<Combobox ItemsSource={Binding Path = Items}
SelectedItem={Binding Path=OneItem}
DisplayMember="item_name"/>
Note that: "item_name" is a property of item element in Items collection. Then you set
Items= new ObservableCollection<Item>(<some items list>);
RaisePropertyChanged("Items");
It's okay for now, But if you want to change the SelectedItem, you cannot set
OneItem= new Item{item_name="abc"};
RaisePropertyChanged("OneItem");
This will not change the SelectedItem on UI.
Instead, you must set the OneItem by searching for item from Items collection
OneItem = Items.Where(x=> x.item_name=="abc").LastOrDefault();
RaisePropertyChanged("OneItem");
Hope this help someone.
精彩评论