Jason Mueller

I've been struggling with an "issue" for the last few hours and am absolutely stumped. Essentially what I want to do is, given a CLR object hierarchy, bind one level of object to some sort of items control and then, at a lower level, bind the items in one of the objects collection properties to a ListBox and update a value on the object when the value changes in the ListBox.

Concrete example: Bind a ListBox to a country's states collection, the items in the list will be ListBoxes bound to the cities collections of the states. When a city is selected, I want a "FavoriteCity" property to be updated on the containing state.

Unfortunately, I am getting what seems to be inconsistent behavior. When I have one level of binding (a ListBox directly bound to a State, with the ItemSource=State.Cities, my property in the souce State object gets updated as expected. When I have multiple levels (ListBox bound to Country, ItemSource=Country.States with embedded ListBoxes bound to State, ItemSource=City) the binding only works if the FavorityCity is set on the State when the items are bound. And what's worse, in another scenario (not my little test repro project) with more levels of binding, I am getting no property setting at all on the source.

I've included all of the source necessary to repro. Sorry if I overcomplicated this. Just create a new WPF Windows Application and past the XAML below into Window1.xaml and the code into a new file (Classes.cs works fine). I also placed light comments in the XAML. To verify that the property was not getting set, I placed a watchpoint on the set { favorityCity = value; } line and had it output the value being set to the debug window.

Any help would be appreciated.

TIA,

Jason

Code Snippet: Window1.xaml

<Window

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:FunkyListBoxSelectedValue="clr-namespace:FunkyListBoxSelectedValue"

x:Class="FunkyListBoxSelectedValue.Window1"

Title="FunkyListBoxSelectedValue" Height="455" Width="694"

>

<Window.Resources>

<DataTemplate x:Key="StateListItemTemplate">

<StackPanel Width="Auto" Height="Auto">

<TextBlock Text="{Binding Path=Name, Mode=Default}" TextWrapping="Wrap"/>

<ListBox Width="Auto" Height="Auto" DisplayMemberPath="Name" ItemsSource="{Binding Path=Cities, Mode=Default}" IsSynchronizedWithCurrentItem="True" SelectedValue="{Binding Path=FavoriteCity, Mode=Default}" SelectedValuePath="Name"/>

</StackPanel>

</DataTemplate>

</Window.Resources>

<Grid>

<Grid.ColumnDefinitions>

<ColumnDefinition Width="0.5*"/>

<ColumnDefinition Width="0.5*"/>

</Grid.ColumnDefinitions>

<ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name" ItemsSource="{Binding Path=Cities, Mode=Default}" SelectedValue="{Binding Path=FavoriteCity, Mode=Default}" SelectedValuePath="Name">

<ListBox.DataContext>

<!-- ***************************************************************

This SelectedValue binding works whether or not a FavoriteCity is specified.

*****************************************************************-->

<FunkyListBoxSelectedValue:State Name="Washington">

<FunkyListBoxSelectedValue:State.Cities>

<FunkyListBoxSelectedValue:City Name="Seattle"/>

<FunkyListBoxSelectedValue:City Name="Spokane"/>

</FunkyListBoxSelectedValue:State.Cities>

</FunkyListBoxSelectedValue:State>

<!--<FunkyListBoxSelectedValue:Country Name="Germany">

<FunkyListBoxSelectedValue:Country.States>

<FunkyListBoxSelectedValue:State Name="Bavaria">

<FunkyListBoxSelectedValue:State.Cities>

<FunkyListBoxSelectedValue:City/>

<FunkyListBoxSelectedValue:City Name="Nrnberg"/>

</FunkyListBoxSelectedValue:State.Cities>

</FunkyListBoxSelectedValue:State>

<FunkyListBoxSelectedValue:State Name="Schleswig-Holstein">

<FunkyListBoxSelectedValue:State.Cities>

<FunkyListBoxSelectedValue:City/>

<FunkyListBoxSelectedValue:City Name="Neumnster"/>

</FunkyListBoxSelectedValue:State.Cities>

</FunkyListBoxSelectedValue:State>

</FunkyListBoxSelectedValue:Country.States>

</FunkyListBoxSelectedValue:Country>-->

</ListBox.DataContext>

</ListBox>

<ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Grid.Column="1" IsSynchronizedWithCurrentItem="True" ItemTemplate="{DynamicResource StateListItemTemplate}" ItemsSource="{Binding Path=States, Mode=Default}">

<ListBox.DataContext>

<FunkyListBoxSelectedValue:Country Name="USA">

<FunkyListBoxSelectedValue:Country.States>

<!-- ***************************************************************

These bindings do not work back to the source if FavorityCity is not specified

(see the DataTemplate for the actual binding).

*****************************************************************-->

<FunkyListBoxSelectedValue:State Name="Kentucky" FavoriteCity="Louisville">

<FunkyListBoxSelectedValue:State.Cities>

<FunkyListBoxSelectedValue:City Name="Lexington"/>

<FunkyListBoxSelectedValue:City Name="Louisville"/>

</FunkyListBoxSelectedValue:State.Cities>

</FunkyListBoxSelectedValue:State>

<FunkyListBoxSelectedValue:State Name="Washington">

<FunkyListBoxSelectedValue:State.Cities>

<FunkyListBoxSelectedValue:City Name="Seattle"/>

<FunkyListBoxSelectedValue:City Name="Spokane"/>

</FunkyListBoxSelectedValue:State.Cities>

</FunkyListBoxSelectedValue:State>

<FunkyListBoxSelectedValue:State Name="Minnesota" FavoriteCity="Duluth">

<FunkyListBoxSelectedValue:State.Cities>

<FunkyListBoxSelectedValue:City Name="Minneapolis"/>

<FunkyListBoxSelectedValue:City Name="Duluth"/>

</FunkyListBoxSelectedValue:State.Cities>

</FunkyListBoxSelectedValue:State>

</FunkyListBoxSelectedValue:Country.States>

</FunkyListBoxSelectedValue:Country>

</ListBox.DataContext>

</ListBox>

</Grid>

</Window>

Code Snippet: Classes.cs

using System;

using System.Collections.Generic;

using System.Text;

namespace FunkyListBoxSelectedValue

{

public class Country

{

private string name;

public string Name

{

get { return name; }

set { name = value; }

}

private List<State> states = new List<State>();

public List<State> States

{

get { return states; }

set { states = value; }

}

}

public class State

{

private string name;

public string Name

{

get { return name; }

set { name = value; }

}

private string favoriteCity;

public string FavoriteCity

{

get { return favoriteCity; }

set { favoriteCity = value; }

}

private List<City> cities = new List<City>();

public List<City> Cities

{

get { return cities; }

set { cities = value; }

}

}

public class City

{

private string name;

public string Name

{

get { return name; }

set { name = value; }

}

}

}



Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Marlon Grech


Hi,

I set up the code that you posted... but I could not understand what exactly is your problem... can you please re explain that part

regards





Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Jason Mueller

Absolutely! Basically what I would expect to happen would be that when I select a city from one of the child ListBoxes in the outer ListBox containing states that the FavoriteCity property of the parent State would be updated. This works in the first top-level ListBox (which is bound to a state), but not for the second top-level ListBox (which is bound to a country) with child list boxes that are bound to states. The second scenario will work, however, for any second-level ListBox that is bound to a State that had the FavoriteCity property set to a valid item value prior to binding.

So, I don't know if I am explaining this clearly, but essentially the behavior I expect would be that any of the ListBox (top-level or otherwise) would set the FavoriteCity property of the bound State given a change in selection of one of its Cities.

Hope that clears it up a little.





Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Marlon Grech

Unfortunatly nothing gets updated when using the XAML that you posted.... where ever i select an item in the listboxes there is nothing being updated on the screen...

am I missing something






Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Jason Mueller

Nothing on the screen should be updated. Basically, if you set a breakpoint on the setter for the FavoriteCity property (or write something to debug) you'll see when it is getting updated and when it is not.

Thanks!

-jason





Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Marlon Grech

finally I can see your problem....

I will have a look at it....






Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Marlon Grech

hi there,

the problem is not the listbox, the problem is that you missed to include the FavoriteCity in the second data source....

replace

<FunkyListBoxSelectedValue:State Name="Washington">

with

<FunkyListBoxSelectedValue:State Name="Washington" FavoriteCity="Seattle">

and the problem should be solved... basically this was making the binding not working since the default value of a string is null...

Regards






Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Jason Mueller

Thank you Marlon. I had that behavior document in the XAML above, but it didn't seem like that was the ultimate answer. I re-validated it though and so far it has held true (that you must specify a default value that exists in the ListBox). I thought I had read in the MSDN docs somewhere that if their was not matching value in the ListBox no item would be selected, but I inferred, for some reason that the binding would still hold. It appears that this is not the case. I want to run one more test on the code that I actually discovered this in (instead of the example that I built and provided) to verify if it holds true in that case. Once I've done that, I'll mark your response as the answer.

Thanks again for taking the time to work through this with me.

-jason





Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Marlon Grech

no problem






Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Jason Mueller

Okay, I was able to validate this behavior in my application. In my application, however, I was unable to get binding to selected value working even when I had a valid value set on the data source. I did determine, however, that the issue was related to my using an ItemsControl instead of a ListBox for my top-level items control. I discovered that when I switched it to a ListBox, the behavior was similar to that described above. I don't want a ListBox though. I want an ItemsControl. I found a workaround, however. It is really quite odd, but I found that if I place a ListBox (collapsed, even) before the ItemsControl (but not after), the control binds fine.

So, I think there are two behaviors I've run across that are not at all intuitive and maybe even bugs

For any Microsoft folks that may be browsing, it would be interesting to know why:

1. In the first ListBox defined at the top of this thread, the binding back to the source when the selected item changes works fine even without a "FavoriteCity" specified. In the seconds ListBox (again at the top of the thread) FavoriteCity is required in order for binding to work.

2. When I have a multiple level binding, with an ItemsControl at the top, the binding does not work unless preceded with a ListBox (presumeably, other controls as well) even if the ListBox itself is not databound. I've included the .XAML file below modified from the one at the top of the thread that highlights this behavior. If you uncomment the ListBox that is commented out, binding works two ways as expected. If you comment the ListBox, the ItemsSource gets bound, but never syncs the FavoriteCity property on the source when a new item selected.

Code Snippet
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:FunkyListBoxSelectedValue="clr-namespace:FunkyListBoxSelectedValue"
    x:Class="FunkyListBoxSelectedValue.Window1"
    Title="FunkyListBoxSelectedValue" Height="455" Width="694"
    >
    <Window.Resources>
       <DataTemplate x:Key="StateListItemTemplate">
           <StackPanel Width="Auto" Height="Auto">
              <TextBlock Text="{Binding Path=Name, Mode=Default}" TextWrapping="Wrap"/>
              <ListBox Width="Auto" Height="Auto" DisplayMemberPath="Name" ItemsSource="{Binding Path=Cities, Mode=Default}" IsSynchronizedWithCurrentItem="True" SelectedValue="{Binding Path=FavoriteCity, Mode=Default}" SelectedValuePath="Name"/>
           </StackPanel>
       </DataTemplate>
    <FunkyListBoxSelectedValue:Country x:Key="countryData"  Name="USA">
     <FunkyListBoxSelectedValue:Country.States>
       <!-- ***************************************************************
            These bindings do not work back to the source if FavorityCity is not specified
            (see the DataTemplate for the actual binding).
            *****************************************************************-->
       <FunkyListBoxSelectedValue:State Name="Kentucky" FavoriteCity="Louisville">
         <FunkyListBoxSelectedValue:State.Cities>
           <FunkyListBoxSelectedValue:City Name="Lexington"/>
           <FunkyListBoxSelectedValue:City Name="Louisville"/>
         </FunkyListBoxSelectedValue:State.Cities>
       </FunkyListBoxSelectedValue:State>
       <FunkyListBoxSelectedValue:State Name="Washington">
         <FunkyListBoxSelectedValue:State.Cities>
           <FunkyListBoxSelectedValue:City Name="Seattle"/>
           <FunkyListBoxSelectedValue:City Name="Spokane"/>
         </FunkyListBoxSelectedValue:State.Cities>
       </FunkyListBoxSelectedValue:State>
       <FunkyListBoxSelectedValue:State Name="Minnesota" FavoriteCity="Duluth">
         <FunkyListBoxSelectedValue:State.Cities>
           <FunkyListBoxSelectedValue:City Name="Minneapolis"/>
           <FunkyListBoxSelectedValue:City Name="Duluth"/>
         </FunkyListBoxSelectedValue:State.Cities>
       </FunkyListBoxSelectedValue:State>
     </FunkyListBoxSelectedValue:Country.States>
    </FunkyListBoxSelectedValue:Country>
 
  </Window.Resources>
    <Grid>
 
       <Grid.ColumnDefinitions>
           <ColumnDefinition Width="0.5*"/>
           <ColumnDefinition Width="0.5*"/>
       </Grid.ColumnDefinitions>
       <!--<ListBox Visibility="Collapsed" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" />-->
     <ItemsControl DataContext="{StaticResource countryData}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Grid.Column="1" ItemTemplate="{DynamicResource StateListItemTemplate}" ItemsSource="{Binding Path=States, Mode=Default}" />
    </Grid>
</Window>

Again, thank you for your help Marlon, I hope this workaround helps someone in the future (unless I'm just doing something wrong).
 
-jason




Re: Windows Presentation Foundation (WPF) Inconsistent ListBox SelectedValue Databinding Behavior

Jason Mueller

Fascinating. I've managed to break binding again. The culprit this time: trying to add another control to my window. If I modify the XAML above by adding a RichTextBox (again, with no bindings or content) prior to the ListBox, my SelectedValue binding breaks again.

Code Snippet

<RichTextBox Width="Auto" Height="Auto"/>

<ListBox Visibility="Collapsed" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" />

<ItemsControl DataContext="{StaticResource countryData}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto" Grid.Column="1" ItemTemplate="{DynamicResource StateListItemTemplate}" ItemsSource="{Binding Path=States, Mode=Default}" />

Can anyone help figure out this one I've done a fair amount of WPF (but am far from what I would call experienced) but it's certainly possible I'm missing something here. If so, please let me know. Otherwise, is this indeed a bug A misunderstanding on my part

Thanks!

-jason