代码之家  ›  专栏  ›  技术社区  ›  jpierson

奇怪的问题绑定到组合框,其中显示值有时显示为空

  •  0
  • jpierson  · 技术社区  · 15 年前

    当绑定到ComboBox时,我看到一个奇怪的问题,其中显示值有时显示为空。但是,这种情况是可重复的,并且发生在从另一个父窗体打开对话框的第二次。如果父窗体关闭并重新打开,则第一次打开它的子对话框时,包含的WPF组合框将正确显示display属性。如果关闭对话框并从同一父窗体重新启动,则组合框不会显示任何显示值,即使我可以验证ViewModel中是否命中了相同的绑定属性。

    <ComboBox ItemsSource="{Binding AvailableVehicles}"
              SelectedValuePath="Value"
              SelectedValue="{Binding SelectedVehicle, Mode=TwoWay}"
              DisplayValuePath="Value.Model" />
    

    为了解释ViewModel的数据结构,它基本上只是一个类,公开了一个可用的hicles集合,其中包含了一个类似于Nullable的对象<&燃气轮机;输入它包装一个Vehicle对象并通过Value属性公开它。每辆车都有一个模型和成本属性。

    我已经排除了这个问题一天多了,我几乎排除了一切,但这是一个错误的组合框本身。因此,在这一点上,我希望有一个合理的解决办法,但如果有人真的可以帮助指出我的代码中的缺陷,这将是伟大的。

    • 我还没能在一个更简单的单窗口WPF示例中重现这个问题。
    • WinForms互操作场景中,我有一个MDI父窗体和子窗体,其中包含wpfusercontrols,以防相关。
    • 如果我在ItemsSource或SelectedValue绑定上将IsAsync设置为True,那么问题就不再发生。
    • 如果我将DisplayValuePath改为ItemsTemplate,并在已定义的DataTemplate内的绑定中放置一个转换器,我注意到传入的值是null,而不是预期的值。
    3 回复  |  直到 15 年前
        1
  •  2
  •   Jeronimo the Black    14 年前

    我也遇到了同样的问题,唯一的解决方法就是在ViewModel中创建两个属性。一个作为选定值(value),但不绑定到组合框,另一个用于绑定(SelectedItem),绑定到SelectedItem。在SelectedItem getter中,我返回Values.FirstOrDefault(x=>x、 Value==Value)在setter中,我按Value.Value设置值。最后,当OnValueChanged属性中的值发生更改时,我通知视图SelectedItem的更改(NotifyPropertyChanged(“SelectedItem”))。。。

        2
  •  2
  •   jpierson    13 年前

    我认为问题与绑定到SelectedValue的对象有关,而绑定到ItemsSource的对象本质上是同一数据的不同实例,恰好是没有重写Equals或==运算符之类的类的实例。从我现在经历的几次来看,由于SelectedValue或者在某些情况下SelectedItem在技术上并不等于绑定项源中的任何对象,因此它被忽略,并且您将在UI中得到一个空白值。

    这种特殊情况下的问题可能是我在关闭窗体时重用了所选的值,但是每次打开对话框时都可能重新生成锁定列表。

    因此,当我在遇到的任何代码中看到这个症状时,首先要检查的是绑定的项类型,并确保SelectedValue或SelectedItem与ItemsSource中的一个项是ReferenceEquals或Equals。现在,我将把这一点再次归咎于WPF中对合理绑定错误反馈的糟糕支持。

        3
  •  0
  •   Trinitron    6 年前

    我和这个问题斗争了大约一个星期,仍然不知道是什么导致了combobox如此奇怪的行为。

    @Jeronimo the Black case),经典组合框控件无法识别SelectedItem仍在基础集合中。然后control internals设置SelectedItem=NULL,UI显示为空。问题是这样的行为有50%的可复制性,在切换到另一个对象或模型后,ItemsSource和SelectedItem之间的互连可以自我恢复。

    在我的例子中,甚至ItemsSource过滤也会导致这些错误。请注意,ParentRegionId属性具有可为null的类型。

        public IEnumerable CityDisplayList
        {
            get
            {
                if (_selectedCity != null && _selectedCity.ParentRegionId != null)
                {
                    return ItemsSource.Where(x => x.ParentRegionId != null);
                }
    
                return Enumerable.Empty<TRegion>();
            }
        }
    

    例2 50%空白(附加过滤)

        public IEnumerable CityDisplayList
        {
            get
            {
                if (_selectedCity != null && _selectedCity.ParentRegionId != null)
                {
                    return ItemsSource.Where(x => x.ParentRegionId != null && x.ParentRegionId == _selectedCity.ParentRegionId);
                }
    
                return Enumerable.Empty<TRegion>();
            }
        }
    

    ItemsSource="{Binding CityDisplayList, Mode=OneWay, IsAsync=True}"
    

    我支持 @jpierson

    解决这个问题的最简单方法就是忘记SelectedItem属性:

    <ComboBox x:Name="cbxCity" ItemsSource="{Binding CityDisplayList}" DisplayMemberPath="RegionName"
                  SelectedItem="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:ControlRegionCombobox}}, Path=SelectedCity}" />
    

    使用“SelectedValue”+“SelectedValuePath”代替:

    <ComboBox x:Name="cbxCity" ItemsSource="{Binding CityDisplayList}" DisplayMemberPath="RegionName"
                  SelectedValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:ControlRegionCombobox}}, Path=SelectedCity.Id}"
                  SelectedValuePath="Id" />