views:

1790

answers:

3

I have two projects. One is working and the other isn't however the differences between them is nothing that I think "should" be of any importance. The first project is the one that is broken and it is the one I am trying to fix. The second project is a little sample project that I created when the first project just won't work at all. Of course the sample works perfectly.

Here is the view for the first project. I have removed a bunch of the "MainWindowTabControlStyle" because it is just the combo box that is broken. I am reasonable certain that the issue is not in the style because it is a copy and paste from the project that is working.

<Grid> 
<TabControl Style="{DynamicResource MainWindowTabControlStyle}"> 
    <TabItem Header="Tab 1"/> 
    <TabItem Header="Tab 2"/> 
</TabControl>
</Grid> 

<Style x:Key="MainWindowTabControlStyle" TargetType="{x:Type TabControl}"> 
... 
    <ComboBox  
        HorizontalAlignment="Right"  
        VerticalAlignment="Top"  
        IsSynchronizedWithCurrentItem="True"  
        ItemsSource="{Binding Path=Subscriptions, Mode=Default}"  
        SelectedItem="{Binding Path=SelectedSubscription, Mode=OneWayToSource}"  
        ItemTemplate="{DynamicResource SubscriptionsItemTemplate}"/> 
... 
</Style> 

<DataTemplate x:Key="SubscriptionsItemTemplate"> 
    <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding Path=DisplayName, Mode=Default}"/> 
    </StackPanel> 
</DataTemplate>

Here is the view model that is set to the DataContext of the MainWindow. The ViewModelBase class is the exact same code that Josh Smith wrote in this months MSDN article.

public sealed class MainWindowViewModel : ViewModelBase 
{ 
    public MainWindowViewModel() 
    { 
    } 

    private ObservableCollection<Subscription> subscriptions; 
    public ObservableCollection<Subscription> Subscriptions 
    { 
        get 
        { 
            if (subscriptions == null) 
            { 
                subscriptions = new ObservableCollection<Subscription>(); 
                subscriptions.Add(new Subscription() { DisplayName = "ABC" }); 
                subscriptions.Add(new Subscription() { DisplayName = "XYZ" }); 
                subscriptions.Add(new Subscription() { DisplayName = "PDQ" }); 
            } 

            return subscriptions; 
        } 
        set { subscriptions = value; } 
    } 

    private Subscription selectedSubscription; 
    public Subscription SelectedSubscription 
    { 
        get { return selectedSubscription; } 
        set { selectedSubscription = value; } 
    } 
}

When I run the project from the debugger the first think that is called is the getter for the Subscriptions collection. Then the setter is called on the SelectedSubscription (it is null). After that I can change the selected item in the combobox till I am blue in the face and the setter for the SelectedSubscription property doesn't get changed again. It is important to note that the combobox does contain the correct values.

In the second project the code is identical but the first thing that is called is the setter for the SelectedSubscription property (it is null) then the getter for the Subscriptions collection is called and finally the setter for the SelectedSubscription is called a second time and it has a value that matches the first item in the Subscriptions collection.

This little jewel has cost me about 5 hours if you have any ideas at all I am willing to try it.

Thanks

+1  A: 

Possibly change

SelectedItem="{Binding Path=SelectedSubscription, Mode=OneWayToSource}"

to

SelectedItem="{Binding Path=SelectedSubscription, Mode=TwoWay}"
geofftnz
Tried that but it doesn't work. One of the things that I was trying to point out in the original post is that I have another project with the exact same View and ViewModel... copy and past line for line. The other project works fine.
Actually after I posted that I started getting binding issues with a Silverlight combobox, so maybe it's contagious.
geofftnz
A: 

The correct way to debug this is to take the working project and to alternately (modify it to match broken code/confirm it works) until it is either identical to the broken project or it breaks. The point at which it breaks tells you where the problem is. Modifying the broken project is typically a lost cause.

As a secondary point, I'd recommend adding the System.Diagnostics namespace to your XAML. It will make errors show up in the Visual Studio Output window.

xmlns:debug="clr-namespace:System.Diagnostics;assembly=WindowsBase"

As a possibly related point (in that it's not really clear what the problem in the broken project is), you might have a look at this StackOverflow question ("Combobox controling Tabcontrol") that relates to:

  • WPF,
  • ComboBoxes,
  • TabControls, and
  • binding between them using SelectedIndex.

There isn't yet a solution to this question, but it is a simpler problem.

Lastly, Josh Smith's MSDN code is pretty large. It's hard to figure out what you changed to add your ComboBox without seeing all the code.

hughdbrown
A: 

Sorry about the delay in getting an answer posted. There was some kind of issue with getting an Open ID up and running.

This is a seriously weird issue.

The resolution to this problem didn't come from the window at all. Prior to the window's show method being called there was another window that was opened as a dialog. In this dialog there was the following resource

<Window.Resources>
    <DropShadowBitmapEffect x:Key="DropShadowEffect" Noise="0" Opacity="0.45" ShadowDepth="5" Softness="0.25"/>
</Window.Resources>

It was was being referenced by two textblocks in the same window as a "DynamicResource". After turning off the dialog and making the application start with the windows that was having the problem it was discovered that the issue was being caused by the dialog window. While I was researching the issue a coworker suggest that I turn the DynamicResource into a StaticResource because there was no reason for it to be dynamic.

This change in a dialog window using an resource that was only available within the scope of the dialog window fixed the binding issue described above in the "Main Window". I guess stranger things can happen.

Ryan Pedersen