Domanda

In una pagina WPF che sto progettando per la mia chiesa, ho due controlli ListBox associati ai risultati di due query Linq-to-Entities: la prima casella / lista contiene tutte le persone che non hanno ancora promesso l'anno, la seconda lista / query contiene tutte le persone che hanno promesso (e i loro impegni associati). In particolare:

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

Quando l'utente dell'applicazione seleziona una famiglia dal primo ListBox, l'elemento ListBox si espande leggermente per mostrare i campi per un impegno, in modo che sia facile aggiungere i dettagli di impegno al secondo ListBox. Sembra qualcosa del genere:

http://wouldbetheologian.com/images/PledgeManager.jpg (Immagine esterna)

Il database sottostante (tra le altre cose) ha una " Famiglia " tabella con 1: molte relazioni con un "impegno" tavolo. E quando l'utente fa clic su " Aggiungi impegno " pulsante, vorrei creare la nuova istanza di Pledge, salvarla nel database e quindi aggiornare i due controlli.

Ma non riesco a capire come farlo. Se provo a farlo nel code-behind, non sembra il gestore eventi per le (n-istanze del) " Aggiungi impegno " il pulsante può fare riferimento ai controlli in questione; e in XAML, se provo a associare i controlli ListBoxItem DataTemplate ai campi Family.Pledge (o Family.Pledge.FirstOrDefault ()), quei campi sono ancora vuoti quando guardo l'oggetto Family corrente nel gestore eventi per Aggiungi Pulsante Impegni.

Qualche idea su come risolverlo? Oppure esiste un modello UI migliore che dovrei esaminare del tutto?

Grazie in anticipo.

È stato utile?

Soluzione 2

Grazie, Andrew, l'hai fatto. La chiave era che dovevo creare un DataContext separato per DockPanel in questione e poi collegarlo a una nuova istanza dell'oggetto Pledge creato più in alto nel modello.

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

Avevo ancora bisogno di conoscere maggiori dettagli per impostare l'oggetto Pledge in modo appropriato, ma sono stato in grado di ottenerli legando la proprietà Tag del pulsante al DataContext del suo padre modello:

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

E da lì, sono stato in grado di gestire il resto in 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);
        }
    }

Mille grazie - mi ha indicato la giusta direzione.

Altri suggerimenti

Il modo più semplice per farlo è quello di avere la classe che rappresenta gli elementi nell'oggetto Items di ListBox per avere tutti i campi a cui si fa riferimento nel DataTemplate. Quindi nel gestore dei pulsanti è possibile accedere alle nuove informazioni di impegno utilizzando il contesto dei dati del pulsante.

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

        //do stuff with pledge
    }

Potrebbe esserci un modo per farlo senza che i campi modellati facciano parte della classe che costituisce ItemsSource per ListBox (sto imparando WPF da solo), ma funziona. Se ciò non aiuta, tornerò indietro più tardi (ora al lavoro).

Comunque, un ottimo lavoro nel creare un'app per la tua chiesa, sembra piuttosto bello.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top