简体   繁体   中英

WPF Combobox binding: can't change selection

After wasting hours on this, following on the heels of my Last Problem , I'm starting to feel that Framework 4 is a master of subtle evil, or my PC is haunted.

I have three comboboxes and a textbox on a WPF form, and I have an out-of-the-box Subsonic 3 ActiveRecord DAL. When I load this "edit record" form, the comboboxes fill correctly, they select the correct items, and the textbox has the correct text. I can change the TextBox text and save the record just fine, but the comboboxes CANNOT BE CHANGED. The lists drop down and highlight, but when you click on an item, the item selected stays the same.

Here's my XAML:

<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
    <TextBlock Width="80">Asset</TextBlock>
    <ComboBox Name="cboAsset" Width="180"  
      DisplayMemberPath="AssetName"
      SelectedValuePath="AssetID" 
      SelectedValue="{Binding AssetID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
    <TextBlock Width="80">Status</TextBlock>
    <ComboBox Name="cboStatus" Width="180" 
      DisplayMemberPath="JobStatusDesc"  SelectedValuePath="JobStatusID"  
      SelectedValue="{Binding JobStatusID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
    <TextBlock Width="80">Category</TextBlock>
    <ComboBox Name="cboCategories" Width="180" 
      DisplayMemberPath="CategoryName"
      SelectedValuePath="JobCategoryID"
      SelectedValue="{Binding JobCategoryID}" ></ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="10,10,0,0">
    <TextBlock Width="80">Reason</TextBlock>
    <TextBox Name="txtReason" Width="380" Text="{Binding Reason}"/>
</StackPanel>

Here are the relevant snips of my code (intJobID is passed in):

SvcMgrDAL.Job oJob;
IQueryable<SvcMgrDAL.JobCategory> oCategories = SvcMgrDAL.JobCategory.All().OrderBy(x => x.CategoryName);
IQueryable<SvcMgrDAL.Asset> oAssets = SvcMgrDAL.Asset.All().OrderBy(x => x.AssetName);
IQueryable<SvcMgrDAL.JobStatus> oStatus = SvcMgrDAL.JobStatus.All();

    cboCategories.ItemsSource = oCategories;
    cboStatus.ItemsSource = oStatus;
    cboAsset.ItemsSource = oAssets;
    this.JobID = intJobID;
    oJob = SvcMgrDAL.Job.SingleOrDefault(x => x.JobID == intJobID);
    this.DataContext = oJob;

Things I've tried:

  • Explicitly setting IsReadOnly="false" and IsSynchronizedWithCurrentItem="True"
  • Changing the combobox ItemSources from IQueryables to Lists .
  • Building my own Job object (plain vanilla entity class using INotifyPropertyChanged ).
  • Every binding mode for the comboboxes.
  • ItemsSource="{Binding}"

The Subsonic DAL doesn't implement INotifyPropertyChanged , but I don't see as it'd need to for simple binding like this. I just want to be able to pick something from the dropdown and save it.

Comparing it with my last problem (link at the top of this message), I seem to have something really wierd with data sources going on. Maybe it's a Subsonic thing?

For some reason the set accessor is hit only on the AssetID property and only the first time. 由于某种原因,set访问器仅在AssetID属性上被命中,并且仅在第一次被命中。 WPF is now heading for WTF :)

You gotta be kidding me- I've removed the binding (ie it only has a displaymemberpath, a valuememberpath and an itemssouce) and it's STILL doing it! 你一定是在开玩笑 - 我已经删除了绑定(即它只有一个displaymember路径,一个valuemember路径和一个itemssouce),它仍然在做它! It accepts your first selection, and then won't change.

WPF Combo Boxes will not change the selected item if the currently selected item and the item that was just selected are considered equal by the object.Equals() method called on the newly selected object (ie newlyslected.Equals(previoslySelected) ).

Overriding the Equals method on the class your binding the combobox items, should resolve the issue your are seeing.

Old topic but I had the same problem and difficulty finding solution. This might help someone else. Clue is above in WPF not detecting a different item has been seleted by user. (Symptom - event ComboBox_SelectionChanged only fires on first selection)

My scenario - lookup combo populated from IList built from a DISTINCT query. In this case the result of using NHibernate ICriteria.SetResultTransformer which only returns SOME fields, importantly NOT including the unique entity ID.

Solution - loop thru' IList after retrieval and give each entity a unique ID. WPF sees them as individuals and behaves appropriately.

Its only a value lookup - its the value content I was after.

The 'temporary' entities are never persisted. In this case it was a better approach than messing with overriding the object's Equals method for the sake of a simple GUI issue. An alternative would be to just copy or tranform the list into a format where WPF uses the value field to determine 'difference'...

I've narrowed it down to the Subsonic objects used as ComboBoxItems. If you create a new class that uses exactly the same code as the relevant parts of the Subsonic one, it works. If you use POCOs/datatables for the combos and Subsonic for the record being edited, it works. But if you use Subsonic for both, it doesn't.

I had hoped to extend the subsonic objects and not have to code a full-blown BLL tier. Looks like I'm faced with doing that or throwing out Subsonic for the DAL. I might post a more specific question for the Subsonic folks.

Many thanks to all who contributed.

Sounds like the field is somehow readonly, or that your change isn't being persisted. After the binding sets the new value, it will re-read the property to ensure that it was actually changed. If your property returns the old value, then it'll be re-selected in the combo box, giving the appearance that the value never changed.

I don't know that DAL, but can you step through the property setter code? You might also have an issue with type conversion.

EDIT reading your comment about the red rectangle -- it sounds as though your property (or something to do with the binding) is raising an exception. Unless, of course, you're using data validation in your UI. You might turn 'Break on all exceptions' in the debugger's settings, assuming you're using Visual Studio.

EDIT 2 You should check the VS Output pane for any error messages related to binding. You can also read this blog post which gives more info on debugging bindings.

It's hard to tell from a small sample of your code but try commenting out the line:

//this.DataContext = oJob; 

and see if this helps.

Setting the DataContext and ItemsSource might be causing a conflict.

Did you write any global style for your combo box which may have a bug or something missing? Or are you using pure default styles for your combobox? Try removing any default styles applied.

Are you wiring up any events? If your code hooks up for event like PreviewMouseLeftButtonUp and marks event as handled then probably combobox may ignore and wont select anything.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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