简体   繁体   English

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

[英]Selected item property doesn't react to binding

I've bound a text box's text and a combo box's selected item to my view model. 我已经将文本框的文本和组合框的选定项绑定到了视图模型。 The elements in the combo box are bound to a static property. 组合框中的元素绑定到静态属性。

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

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

It seems that the binding is in effect because the text box receives the correct content. 绑定似乎有效,因为文本框接收到正确的内容。 The combo box gets it's values in the list correctly too. 组合框也可以正确获取列表中的值。 However, the issue is that the selection isn't being made. 但是,问题是没有进行选择。

At first I though that it had to do with the fact that some controllers have another default for Mode , so I tried explicitly setting it to two-way for the combo box. 最初我虽然与某些控制器为Mode设置了另一个默认值的事实有关,所以我尝试将组合框显式设置为双向。 No difference in behavior as far I could see. 据我所知,行为没有差异。

What can I be doing wrong. 我做错了什么。 How to resolve it (or at least trouble-shoot)? 如何解决(或至少解决问题)?

I've followed every hint from all I could find as the hints are more or less the same everywhere. 我遵循了我所能找到的所有提示,因为各地的提示大致相同 Nothing worked, accept the approach of setting the selected index instead of the selected item . 什么都没做,请接受设置选定索引而不是选定项目的方法 Sadly, I don't see how I could achieve that. 可悲的是,我不知道如何实现这一目标。

I've tried adding DisplayMemberPath , as suggested. 我尝试按照建议添加DisplayMemberPath That didn't work and the items of the combo box are not present anymore. 没有工作组合框的项目不再出现。 I'm guessing that DisplayMemberPath refers to where to get stuff to itemize from whatever is referred to in ItemSource (and there's no Picked in there). 我猜想DisplayMemberPath指的是从ItemSource中引用的内容中获取要逐项列出的东西的位置 (并且那里没有Picked )。

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

Full (almost) source code for the senario senario的完整(几乎)源代码

View model assignment to the main window. 查看模型分配到主窗口。

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

The view model of used (circumsized version regarding the components in question in order to be a minimal example ). 所用的视图模型(关于所讨论组件的简化版本,以作为最小示例 )。

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));
  }
}

Main window's code behind (the parts that relate to used controls and events). 主窗口后面的代码(与使用的控件和事件有关的部分)。 I also have a grid view called ThingListing in my markup, which is bound to AllThingsView in my view model. 我的标记中还有一个名为ThingListing的网格视图,该视图绑定到我的视图模型中的AllThingsView When I click on a record in it, the event fired is supposed to update the value of CurrentThing and change the tab to the one where the bound controls are placed. 当我单击其中的一条记录时,触发的事件应该更新CurrentThing的值,并将选项卡更改为放置绑定控件的选项卡。 Everything seems to get in the right places accept the selected items for combo boxes. 一切似乎都在正确的地方接受了组合框的选定项目。 I also have a convenience extension method Get . 我也有一个便捷的扩展方法Get It does what you intuitively think it would (tested back and forth since forever). 它做到了您直觉上会想到的(永远以来反复测试)。

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));
  }
}

For a ComboBox in WPF its essential to have SelectedItem set to an object present in ItemsSource in your case in IEnumerable<PickType> AllPickables and in XAML ItemSource must be positioned before SelectedItem (as you already have it) 对于ComboBox在WPF它必须有SelectedItem设置存在于一个对象ItemsSource在您的案件中IEnumerable<PickType> AllPickables和XAML ItemSource 之前必须定位SelectedItem (因为你已经拥有它)

At the time the ComboBox sees SelectedItem it must be present in its Items . ComboBox看到SelectedItem它必须出现在其Items This rule also applies at a later time ie when NotifyPropertyChanged fires. 此规则也适用于以后的时间,即当NotifyPropertyChanged触发时。

Further: CurrentThing should have the same type PickType 此外: CurrentThing应该具有相同的类型PickType

public PickType CurrentThing { ... }

and CurrentThing shoud point to one existing member in AllPickables (or set to null for no selection). CurrentThing应该指向AllPickables一个现有成员(或设置为null表示没有选择)。

It looks like the comparison fails when the view model is being read. 似乎在读取视图模型时比较失败。 This likely happens because of incorrect/missing implementation of comparison methods. 这可能是由于比较方法的不正确/缺少实现而发生的。 Try implementing Equals and GetHash and see if it works. 尝试实现Equals和GetHash并查看其是否有效。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM