所选项目 属性 对绑定没有反应

Selected item property doesn't react to binding

我已将文本框的文本和组合框的选定项绑定到我的视图模型。组合框中的元素绑定到静态 属性.

<TextBox x:Name="Texty" 
  Text="{Binding CurrentThing.Texty}" ... />

<ComboBox x:Name="Picky"
  ItemsSource="{x:Static local:MainWindow.AllPickables}"
  SelectedItem="{Binding CurrentThing.Picked}" ... />

似乎绑定生效了,因为文本框收到了正确的内容。组合框也正确地在列表中获取它的值。但是,问题是没有进行选择。

起初我认为这与某些控制器对 Mode 有另一个默认值有关,所以我尝试将其明确设置为组合框的双向.据我所知,行为没有区别。

我做错了什么。如何解决(或至少排除故障)?

我已遵循我能找到的所有提示,因为提示无处不在 more or less the same。没有任何效果,接受设置选定的 index 而不是选定的 item 的方法。可悲的是,我不知道如何才能做到这一点。

我尝试按照建议添加 DisplayMemberPath。那没有用 并且 组合框的项目不再存在。我猜 DisplayMemberPath 指的是从 ItemSource 中提到的任何内容中获取要逐项列出的内容的位置(并且没有 Picked in there).

<ComboBox x:Name="Picky"
  ItemsSource="{x:Static local:MainWindow.AllPickables}"
  SelectedItem="{Binding CurrentOrder}"
  DisplayMemberPath="Picked" ... />

senario 的(几乎)完整源代码

查看主模型分配 window。

<Window.DataContext>
  <local:Presenter/>
</Window.DataContext>

所使用的视图模型(关于相关组件的简化版,以便成为最小示例)。

public class Presenter : INotifyPropertyChanged
{
  private ObservableCollection<Thing> _allThings;

  private Thing _currentThing;
  public Thing CurrentThing
  {
    get { return _currentThing; }
    set { _currentThing = value; OnPropertyChanged(); }
  }

  public ListCollectionView AllThingsView { get; set; }

  private IEnumerable<PickType> _allPickables;
  public IEnumerable<PickType> AllPickables
  {
    get { return _allPickables; }
    set { _allPickables = value; OnPropertyChanged(); }
  }

  public Presenter()
  {
    _allThings = new ObservableCollection<Thing>(DataAccessor.GetThings());
    AllThingsView = new ListCollectionView(_allThings);
    _allPickables = DataAccessor.GetPickables();
  }

  public event PropertyChangedEventHandler PropertyChanged;

  [NotifyPropertyChangedInvocator]
  protected virtual void OnPropertyChanged([CallerMemberName] String name = null)
  {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
  }
}

主要window的隐藏代码(与使用的控件和事件相关的部分)。我的标记中还有一个名为 ThingListing 的网格视图,它在我的视图模型中绑定到 AllThingsView。当我单击其中的一条记录时,触发的事件应该更新 CurrentThing 的值并将选项卡更改为放置绑定控件的选项卡。一切似乎都在正确的地方接受组合框的选定项目。我还有一个方便的扩展方法 Get。它会做你直觉上认为会做的事(一直来回测试)。

public partial class MainWindow : Window
{
  public MainWindow()
  {
    InitializeComponent();
    DataContext = new Presenter();
  }

  private void ThingListing_OnMouseDoubleClick(Object sender, MouseButtonEventArgs eventArgs)
  {
    DataContext.Get<Presenter>().CurrentThing
      = sender.Get<DataGrid>().CurrentItem.Get<Thing>();

    Dispatcher.BeginInvoke((Action)(() => tabControl.SelectedIndex = 1));
  }
}

对于 WPF 中的 ComboBox,在 IEnumerable<PickType> AllPickables 和 XAML 中,必须将 SelectedItem 设置为存在于 ItemsSource 中的对象ItemSource 必须位于 之前 SelectedItem (因为你已经有了)

ComboBox 看到 SelectedItem 时,它必须存在于它的 Items 中。此规则也适用于稍后时间,即当 NotifyPropertyChanged 触发时。

进一步:CurrentThing应该有相同的类型PickType

public PickType CurrentThing { ... }

CurrentThing 应该指向 AllPickables 中的一个现有成员(或者设置为 null 表示不选择)。

看起来在读取视图模型时比较失败。这可能是因为 incorrect/missing 比较方法的实施。尝试实施 Equals 和 GetHash,看看它是否有效。

public override bool Equals(Object input)
{
  return Id == ((Thing)input)?.Id;
}

public override int GetHashCode()
{
  return base.GetHashCode();
}