0

I have a custom class called ApplicationUser which has a number of properties. The ones of importance here are GivenName and Surname.

In the ctor for the window I have code which returns a List called _allUsers. This call is successful and the list is filled with the appropriate number of ApplicationUsers

So I then do something like:

_allUsers = CachingLayer.Get<List<ApplicationUser>>("allUserInformation");
cboListOfUsers.DataContext = _allUsers;

And the XAML:

        <ComboBox Name="cboListOfUsers" ItemsSource="{Binding}" IsEnabled="{Binding Path = IsChecked, ElementName=rbAssignedTo}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock>
                    <TextBlock.Text >
                        <MultiBinding StringFormat=" {0}, {1} ">
                            <Binding Path="Surname" />
                            <Binding Path="GivenName" />
                        </MultiBinding>
                    </TextBlock.Text>
                    </TextBlock>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

But there's no joy (the Combo Box remains resolutely empty)

What am I doing wrong here?

noonand
  • 2,763
  • 4
  • 26
  • 51
  • 1
    Look at your output window and see if there are any binding errors. – myermian Apr 13 '12 at 22:46
  • 2
    Try taking off the IsEnabled part. – paparazzo Apr 13 '12 at 22:48
  • @Blam - I have tried taking that off already, sorry for not specifying... – noonand Apr 14 '12 at 09:45
  • @m-y No binding errors evident in the output window – noonand Apr 14 '12 at 09:46
  • @m-y Now getting System.Windows.Data Warning: 40 : BindingExpression path error: 'GivenName' property not found on 'object' ''ApplicationUser' (HashCode=257207)'. BindingExpression:Path=GivenName; DataItem='ApplicationUser' (HashCode=257207); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String') errors in my output window – noonand Apr 14 '12 at 10:50

3 Answers3

2

OK then you need to set you DataContext to the code behind as a whole up in the top in Window

   DataContext="{Binding RelativeSource={RelativeSource self}}"

Make AllUsers a public property that returns allUsers

Bind to AllUsers

 ItemsSource="{Binding Path=AllUsers}"
paparazzo
  • 44,497
  • 23
  • 105
  • 176
2

It was the BindingExpression path error: 'GivenName' property not found on 'object' ''ApplicationUser' error message that finally solved it for me!

This is going to make everyone sick, but as I was preparing to edit my question to include some screenshots to prove that "The blasted thing does have a property called x and y and what the hell does the Output window know!" I said I'd better check that I had implemented the object ApplicationUser correctly.

Sure enough I hadn't, I had left what I had thought were properties as publicly mutable fields(!). I turned them into auto-props and then my code as originally posted worked.

I'd like to apologise to and thank all who read the question, commented and suggested answers. My purpose in leaving this answer here is twofold, to help anyone else out that may find themselves in a similar situation and also to serve as a reminder to myself that sometimes if you can't see the wood for the trees then you may need to step back a bit.

noonand
  • 2,763
  • 4
  • 26
  • 51
  • 1
    Oh, man, what a pain! But you got it, that's all that matters. And so true about stepping back. Back in the day at school I had a professor telling me that. Once he said, denis, get your forehead out of the monitor and the keyboard! Thanks for posting this, it was driving me nuts, I would have been thinking about this all weekend – denis morozov Apr 14 '12 at 17:36
1

I think your issue is in timing which is caused by where your are assigning DataContext. XAML resovles

ItemsSource="{Binding}"

during the InitializeComponent(), but you might be iinit'ing list after, which is too late.

When XAML gets build/resolved, comboBox takes the Binding, but there is nothing there. Many ways to solve:

  1. the easiest way, is to do it in XAML:

  2. why even set DataContext, doesn't look like you're doing anything special, it's only a list, not a full blown ViewModel..

    remove:

    cboListOfUsers.DataContext = _allUsers;
    

    add/replace with

    cboListOfUsers.ItemsSource = _allUsers;
    

3.Init your _allUsers before InitializeComponent(), then assign it to the DataContext

One more suggestion - debug your bindings in xaml, add:

ItemsSource="{Binding, diagnostics:PresentationTraceSources.TraceLevel=High}"

check you output window, if you have an exception, then I am right, the binding tries to resolve, but there is nothing there...

I think that should work..

Also, check out this post: Why are DataContext and ItemsSource not redundant?

Community
  • 1
  • 1
denis morozov
  • 6,236
  • 3
  • 30
  • 45
  • Attempting to assign the DataContext of the combo box before InitializeComponent() causes a NullReferenceException – noonand Apr 14 '12 at 10:41
  • Attempting to debug the bindings causes an error: The tag 'Binding,' does not exist in XML namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'. Line 13 Position 110 – noonand Apr 14 '12 at 10:48
  • 1
    hmm, I can't believe that this won't work, in the constructor: _allUsers = CachingLayer.Get>("allUserInformation"); InitializeComponent(); cboListOfUsers.ItemSource= _allUsers; – denis morozov Apr 14 '12 at 15:55
  • yes it works in the order that you have there, but the underlying issue is not the order, it is the way the class was defined – noonand Apr 15 '12 at 17:06