当源更改时,组合框 SelectedItem 不会更新

发布于 2024-09-14 14:57:30 字数 2244 浏览 9 评论 0原文

我有一个实现 INotifyPropertyChanged 的​​视图模型。此 viewModel 上有一个名为 SubGroupingView 的属性。该属性绑定到组合框的选定项目。当我更改组合框时,源属性会很好地更新,但是当我更改源属性或初始化控件时,combobox.selectedItem 不反映属性中存在的内容。< br> 下面是一些可以帮助您入门的代码:

<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">

属性引发 PropertyChanged 事件,TraceSource 输出显示绑定检测到它并传输了值,只是组合框没有反映它。任何想法都将受到欢迎!

编辑:
跟踪源的输出如下:

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)  

这是源属性的代码:

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");
            base.OnPropertyChanged("IsReady");
        }

    }
}

注意:ViewModelBase 实现 INotifyPropertyChange

回答
我重载了 ==、!= 运算符、GetHashCode()Equals(object),现在它运行良好。感谢您的帮助!

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.
Here is some code to get you started:

<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");
            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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

萌吟 2024-09-21 14:57:30

从 SubGroupingView 返回的对象必须“等于”ComboBox.Items 中的对象之一(这意味着它必须位于 Columns 集合中)。因此,如果您执行“a.Equals(b)”,则需要返回 true。

如果它们在功能上相同,但比较时不返回 true,那么这就是您的问题。您需要返回相同的对象,或者重写 Equals 方法(以及可能的 == 和 != 运算符)。

如果这是您的问题,则与此问题中的问题相同。

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.

萌吟 2024-09-21 14:57:30

您的 ComboBox 上的 IsSynchronizedWithCurrentItem 是否设置为 false?您可以尝试显式设置 IsSynchronizedWithCurrentItem="True" 并查看是否有帮助。

Is IsSynchronizedWithCurrentItem on your ComboBox perhaps set to false? You could try explicitly setting IsSynchronizedWithCurrentItem="True" and see if that helps.

浮世清欢 2024-09-21 14:57:30

@CodeNaked 的答案是正确的。但就我而言,仅重写 Object.Equals 就会引发 StackOverflowException。我认为整个答案是实现完整的 IEquatable,这意味着实现其 Equals 方法并重写 Object.Equals(Object) 和 Object.GetHashCode 方法,如 此示例(请参阅“备注”部分的末尾 - “实施者注意事项” - 和“示例”部分)。

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).

鹤舞 2024-09-21 14:57:30

根据我的经验,您需要通过从 ItemsSource 搜索来设置 SelectedItem。

对于 MVCC 示例,如果您创建了一个组合框,

<Combobox ItemsSource={Binding Path = Items} 
SelectedItem={Binding Path=OneItem} 
DisplayMember="item_name"/>

请注意:“item_name”是 Items 集合中 item 元素的属性。
那么你设置

Items= new ObservableCollection<Item>(<some items list>);
RaisePropertyChanged("Items");

暂时就可以了,但是如果你想改变SelectedItem,你就不能设置

OneItem= new Item{item_name="abc"};
RaisePropertyChanged("OneItem");

这不会改变UI上的SelectedItem。

相反,您必须通过从 Items 集合中搜索项目来设置 OneItem

OneItem = Items.Where(x=> x.item_name=="abc").LastOrDefault();
RaisePropertyChanged("OneItem");

希望这对某人有帮助。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文