Question

Dans une page WPF que je conçois pour mon église, j'ai deux contrôles ListBox liés aux résultats de deux requêtes Linq-to-Entities: la première listbox / requête contient tous les gens qui ne se sont pas encore engagés L'année, la deuxième liste contient tous les gens qui ont promis (et les promesses associées). Plus précisément:

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 };

Lorsque l'utilisateur de l'application sélectionne une famille dans le premier contrôle ListBox, l'élément ListBox se développe légèrement pour afficher les champs d'un gage, de sorte qu'il est facile d'ajouter les détails du gage au second ListBox. Cela ressemble à quelque chose comme ça:

http://wouldbetheologian.com/images/PledgeManager.jpg (image hors site)

La base de données sous-jacente (entre autres) a une "Famille". table avec une relation 1: plusieurs avec un "engagement" table. Et lorsque l'utilisateur clique sur le lien "Ajouter un engagement". bouton, j'aimerais créer la nouvelle instance Pledge, l'enregistrer dans la base de données, puis actualiser les deux contrôles.

Mais je n'arrive pas à comprendre comment faire cela. Si j'essaie de le faire dans le code-behind, cela ne semble pas être le gestionnaire d'événements pour les (n-instances du) "Ajouter un engagement". bouton peut référencer les contrôles en question; et en XAML, si j'essaie de lier les contrôles ListBoxItem DataTemplate aux champs Family.Pledge (ou Family.Pledge.FirstOrDefault ()), ces champs sont toujours vides lorsque je regarde l'objet Family en cours dans le gestionnaire d'événements pour la propriété Add. Bouton de promesse.

Avez-vous des idées sur la façon de résoudre ce problème? Ou y a-t-il un meilleur modèle d’assurance-chômage que je devrais absolument examiner?

Merci d'avance.

Était-ce utile?

La solution 2

Merci, Andrew, qui l’a fait. La clé était que je devais créer un DataContext distinct pour le DockPanel en question, puis le lier à une nouvelle instance de l'objet Pledge créé plus haut dans le modèle.

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.Resources>
                    <local:Pledge x:Key="pledge" />
                </Grid.Resources>

                <DockPanel DataContext="{Binding Source={StaticResource pledge}}" >
                    <TextBox Name="txtAmount" Text="{Binding Path=Amount}" />
                    <TextBox Name="txtEnvelopeID" Text="{Binding Path=EnvelopeID}" />
                    <!-- Bind the Tag property of the Button to the DataContext of the ListBoxItem, i.e.  the current Family object -->
                    <Button Tag="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext}" Name="addPledge" Click="addPledge_Click"  >
                        Add Pledge -->
                    </Button>
                </DockPanel>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

J'avais toujours besoin de connaître davantage de détails pour configurer l'objet Pledge correctement, mais j'ai pu les obtenir en liant la propriété Tag du Button au DataContext de son parent basé sur un modèle:

<Button 
    Tag="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext}" 
    Name="addPledge" 
    Click="addPledge_Click" 
/>

Et à partir de là, j'ai pu gérer le reste en code-behind:

    private void addPledge_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            // Set any additional necessary properties.
            Button button = (Button)sender;
            Pledge pledge = (Pledge)button.DataContext;
            pledge.PledgeYear = (PledgeYear)cboYear.SelectedItem;
            pledge.Family = (Family)button.Tag;

            // Update the database and refresh the Listboxes.
            entities.AddToPledge(pledge);
            entities.SaveChanges();
            LoadUnpledgedListBox();
            LoadPledgedListBox();
        }
        catch (System.Data.UpdateException ex)
        {
            MessageBox.Show("Error updating database: " + ex.Message);
        }
        catch (System.Exception ex)
        {
            Classes.Utils.HandleGenericError(ex);
        }
    }

Merci beaucoup - cela m'a orienté dans la bonne direction.

Autres conseils

La méthode la plus simple consiste à faire en sorte que la classe représentant les éléments de votre ListBox ItemsSource contienne tous les champs que vous référencez dans votre DataTemplate. Ensuite, dans votre gestionnaire de boutons, vous pouvez accéder aux nouvelles informations de promesse en utilisant le contexte de données du bouton.

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

        //do stuff with pledge
    }

Il existe peut-être un moyen de le faire sans que les champs basés sur un modèle fassent partie de la classe qui constitue le ItemsSource pour le ListBox (je viens d’apprendre à utiliser WPF), mais cela fonctionne. Si cela ne vous aide pas, je reviendrai plus tard (au travail maintenant).

Quoi qu’il en soit, fabuleux travail de création d’une application pour votre église, il est plutôt beau.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top