views:

30

answers:

1

I have a ComboBox that uses an ItemTemplate as shown below. Somehow the Text property of the text box defined in the item template gets disconnected from the binding and stops being updated when the selected item changes.

The ComboBox.ItemsSource is bound to a DependencyProperty that is list of CatheterDefinition objects. The ComboBox.SelectedItem is bound to a DependencyProperty that is a single CatheterDefinition object.

<ComboBox
  AutomationProperties.AutomationId="CatheterInfoModelFieldID"
  VerticalAlignment="Center" HorizontalAlignment="Stretch"
  ItemsSource="{x:Static PumpAndCatheter:CatheterInfoViewModel.CatheterModelDefinitions}"
  SelectedItem="{Binding ElementName=UserControl, Path=ViewModel.SelectedCatheterModel, Mode=TwoWay, NotifyOnSourceUpdated=True}"
  SourceUpdated="HandleModelSourceUpdated">
  <ComboBox.ItemContainerStyle>
    <!-- A style used to set the AutomationID based on the item goes here -->
  </ComboBox.ItemContainerStyle>
  <ComboBox.ItemTemplate>
    <DataTemplate>
      <!-- This line below is the location of the problem -->
      <TextBlock Text="{Binding Converter={StaticResource CatheterModelDefinitionToStringConverter}}">
        <!-- A style used to set the AutomationID based on the item goes here -->
      </TextBlock>
    </DataTemplate>
  </ComboBox.ItemTemplate>
</ComboBox>

I have an automated test that produces a very strange behavior (I saw the same behavior a few time during the initial development of the code, but was unable to reproduce it manually) - The test that reproduces this selects an item form the ComboBox, then goes to another part of the application and takes some actions that end up saving this change in a data model. When the test returns to the screen with this ComboBox, it tries to select another item from the ComboBox. The SelectedItem changes, and the values that it is bound to change, BUT the text in the ComboBox does not change - somehow the binding to the Text property of the text box gets broken (or something)... The binding still executes (the converter still runs when the selection changes and it converts to the correct value), but the text property is never updated.

Thoughts? (I can't provide an example of this because it is a huge application and it is only reproducible under one test that I know of)

A: 

Broken bindings are most of the time caused by not calling (or not correctly calling) the OnPropertyChanged("PropName") method.

Without seeing your underlying implementation, I would say that this is most likely the source of the problem.

Nate Noonen
The properties that the combobox is bound to are dependency properties. There is no need to call OnPropertyChanged.Also, I changed the item template to use a label instead of a textbox. Since the result of the conversion is a string, the default data template for type string is used, resulting in the following visual tree to display the value: <Label> <Border> <ContentPresenter> <TextBox> </ContentPresenter> </Border> </Label>Interestingly, the Label.Content property is set correctly, but the Textbox.Text property is still broken.
Andy
Also, I believe the disconnect may be occurring when I leave the screen... I have not confirmed this, but it may occur earlier than I originally thought.
Andy
Is your nested view model a DependencyProperty?
Nate Noonen
The ViewModel referenced in the SelectedItem binding has been both a dependency property and a regular property (set in the constructor of the UserControl) while I have been debugging this. The problem happens in both cases.
Andy
"the Label.Content property is set correctly, but the Textbox.Text property is still broken" Are you using the same converter on the label?Also, have you used any tool to see what WPF events are firing and where they are handled? Your property changed may be lost somewhere.These are shots in the dark since broken bindings are source specific and could be the result of any number of things.
Nate Noonen
Here is what I changed the Item template to... same converter, just setting the Label.Content property instead of TextBox.Text. <ComboBox.ItemTemplate> <DataTemplate> <Label Padding="0" Content="{Binding Converter={StaticResource CatheterModelDefinitionToStringConverter}}"/> </DataTemplate> </ComboBox.ItemTemplate>
Andy
I have not used and tools for looking at the events.
Andy
Also, I have only been able to observer this behavior when snoop (or UISpy) is attached. In Snoop, The "ValueSource" of the TextBox.Text property changes from "ParentTemplate" to "Local" at some point when I navigate through my application.
Andy
I just tested it and if I attach snoop, but don't navigate through the tree to the combobox, it does not fail.
Andy
OK... there must be some kind of timing issue going on. I can reproduce the issue if I have snoop open and I am examining the textblock in question when I navigate through my application. If I have snoop open but am examining some other item, it does not fail. I will check to see if the automated test is doing something similar.
Andy
I have reproduced this on many different text blocks in my application. In one case the Text binding is a two way binding, but the converter's ConvertBack method is not implemented. In that case it is throwing an exception. This leads me to believe that something is setting the text of the textbox control, which in this case causes a conversion exception; in other cases breaks the OneWay bindings.
Andy
Issue solved? Also, in WPF keep an eye on the output window. All binding exceptions are thrown into there.
Nate Noonen
I tried making a small application to reproduce the issue but had no luck. I am still looking into the interaction of Snoop. I will be getting the source code and trying to debug it. Something is setting the text property of the textblock directly. It is not a binding error.
Andy
I was able to duplicate this by attaching Snoop to "Microsoft Expression Blend 2". The steps I used were:1) open Expression Blend2) open a project3) Select an item in the "Objects and Timeline" area (ex: a grid)4) Use snoop to examine the textbox that shows the Type of element selected in the properties area "Type [Grid]"5) click on the project tab (which makes the properties area disappear6) Click on the properties tab 9to show the properties area7) select a control with a different type (ex: a label)Result: even though the label is selected, the Type still shows as "Grid"
Andy