Wpf – Referencing controls in a WPF DataTemplate

code-behinddatatemplatelistboxwpfxaml

In a WPF page that I'm designing for my church, I have two ListBox controls bound to the results of two Linq-to-Entities queries: the first listbox/query contains all the folks who haven't yet pledged for the year, the second listbox/query contains all the folks who have pledged (and their associated pledges). Specifically:

var familiesWithNoPledges = from family in entities.Family.Include("Pledge")
    where !family.Pledge.Where(p => p.PledgeYearID == pledgeYear).Any()
    select family;

var familiesWithPledges = from family in entities.Family
    join pledge in entities.Pledge.Include("PledgeFrequency").Where(p => p.PledgeYearID == pledgeYear) on family equals pledge.Family
    select new { family, pledge };

When the user of the application selects a family from the first ListBox, the ListBox item expands slightly to show the fields for a pledge, so that it's easy to add the pledge details to the second ListBox. It looks something like this:

http://wouldbetheologian.com/images/PledgeManager.jpg
(Offsite Image)

The underlying database (among other things) has a "Family" table with a 1:many relationship to a "Pledge" table. And when the user clicks the "Add Pledge" button, I'd like to create the new Pledge instance, save it to the database, and then refresh the two controls.

But I can't figure out how to do that. If I try to do it in the code-behind, it doesn't seem like the event handler for the (n-instances of the) "Add Pledge" button can reference the controls in question; and in XAML, if I try to bind the ListBoxItem DataTemplate controls to the Family.Pledge (or Family.Pledge.FirstOrDefault()) fields, those fields are still empty when I look at the current Family object in the event handler for the Add Pledge button.

Any thoughts on how to solve this? Or is there a better UI model I should look at altogether?

Thanks in advance.

Best Answer

The easiest way to do it is to have the class that is representing items in your ListBox ItemsSource to have all the fields that you are referencing in your DataTemplate. Then in your button handler you can access the new pledge info by using the data context of the button.

    private void AddPledge_Click(object sender, RoutedEventArgs e)
    {
        Button b = sender as Button;
        PotentialPledge p = b.DataContext as PotentialPledge;

        //do stuff with pledge
    }

There might be a way to do this without having the templated fields be part of the class that makes up the ItemsSource for the ListBox (just learning WPF myself), but this works. If that doesn't help, I'll look back later (off to work now).

Anyway, awesome job making an app for your church, it's looking pretty good.