Frage

Auf einer WPF-Seite, die ich für meine Kirche entwerfe, habe ich zwei ListBox-Steuerelemente, die an die Ergebnisse von zwei Linq-to-Entities-Abfragen gebunden sind:Das erste Listenfeld/die erste Abfrage enthält alle Personen, die für das Jahr noch keine Zusagen abgegeben haben, das zweite Listenfeld/die zweite Abfrage enthält alle Personen, die die Zusagen abgegeben haben (und die damit verbundenen Zusagen).Speziell:

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

Wenn der Benutzer der Anwendung eine Familie aus der ersten ListBox auswählt, wird das ListBox-Element leicht erweitert, um die Felder für ein Pfand anzuzeigen, sodass die Pfanddetails einfach zum zweiten ListBox hinzugefügt werden können.Es sieht ungefähr so ​​aus:

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

Die zugrunde liegende Datenbank verfügt (unter anderem) über eine „Family“-Tabelle mit einer 1:n-Beziehung zu einer „Pledge“-Tabelle.Und wenn der Benutzer auf die Schaltfläche „Pledge hinzufügen“ klickt, möchte ich die neue Pledge-Instanz erstellen, sie in der Datenbank speichern und dann die beiden Steuerelemente aktualisieren.

Aber ich kann nicht herausfinden, wie das geht.Wenn ich versuche, dies im Code-Behind zu tun, sieht es nicht so aus, als ob der Event-Handler für die (n-Instanzen der) Schaltfläche „Pledge hinzufügen“ auf die betreffenden Steuerelemente verweisen kann;Und wenn ich in XAML versuche, die ListBoxItem DataTemplate-Steuerelemente an die Felder Family.Pledge (oder Family.Pledge.FirstOrDefault()) zu binden, sind diese Felder immer noch leer, wenn ich mir das aktuelle Family-Objekt im Ereignishandler für das Hinzufügen ansehe Schaltfläche „Versprechen“.

Irgendwelche Ideen, wie man das Problem lösen kann?Oder gibt es ein besseres UI-Modell, das ich mir insgesamt ansehen sollte?

Dank im Voraus.

War es hilfreich?

Lösung 2

Danke, Andrew, das hat es geschafft.Der Schlüssel war, dass ich einen separaten DataContext für das betreffende DockPanel erstellen und ihn dann an eine neue Instanz des Pledge-Objekts binden musste, das weiter oben in der Vorlage erstellt wurde.

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

Ich musste noch mehr Details wissen, um das Pledge-Objekt richtig einzurichten, aber ich konnte sie erhalten, indem ich die Tag-Eigenschaft des Buttons an den DataContext seines übergeordneten Templates bindete:

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

Und von da an konnte ich den Rest im Code-Behind erledigen:

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

Vielen Dank – das hat mir die richtige Richtung gezeigt.

Andere Tipps

Der einfachste Weg, dies zu tun, besteht darin, die Klasse, die Elemente in Ihrer ListBox ItemsSource darstellt, so zu gestalten, dass sie alle Felder enthält, auf die Sie in Ihrer DataTemplate verweisen.Dann können Sie in Ihrem Button-Handler auf die neuen Pfandinformationen zugreifen, indem Sie den Datenkontext der Schaltfläche verwenden.

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

        //do stuff with pledge
    }

Möglicherweise gibt es eine Möglichkeit, dies zu tun, ohne dass die Vorlagenfelder Teil der Klasse sind, die die ItemsSource für die ListBox bildet (ich lerne gerade WPF selbst), aber das funktioniert.Wenn das nicht hilft, schaue ich später noch einmal nach (ich mache mich jetzt an die Arbeit).

Wie auch immer, tolle Arbeit bei der Erstellung einer App für Ihre Kirche, sie sieht ziemlich gut aus.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top