Pergunta

Em uma página do WPF que estou projetando para minha igreja, tenho dois controles de caixa de listagem vinculados aos resultados de duas consultas de Linq-to-Entidades: a primeira caixa de listagem/consulta contém todas as pessoas que ainda não se comprometeram ao ano, A segunda caixa de listagem/consulta contém todas as pessoas que prometeram (e suas promessas associadas). Especificamente:

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 o usuário do aplicativo seleciona uma família na primeira caixa de listagem, o item da ListBox se expande um pouco para mostrar os campos para uma promessa, para que seja fácil adicionar os detalhes de penhor à segunda caixa de listagem. Parece algo assim:

http://wouldbetheologian.com/images/pledGanager.jpg (Imagem externa)

O banco de dados subjacente (entre outras coisas) tem uma tabela de "família" com um relacionamento 1: Muitos com uma tabela de "compromisso". E quando o usuário clicar no botão "Adicionar a penhor", gostaria de criar a nova instância de penhor, salve -a no banco de dados e atualize os dois controles.

Mas não consigo descobrir como fazer isso. Se eu tentar fazê-lo no código-behind, não parece o manipulador de eventos para as (botões N-Instances of the) "Adicionar a penhor" podem fazer referência aos controles em questão; E em XAML, se eu tentar vincular os controles ListBoxItem Datatemplate aos campos Family.Pledge (ou família.pledge.FirstorDefault ()), esses campos ainda estão vazios quando olho para o objeto familiar atual no manipulador de eventos para adição Botão de penhor.

Alguma idéia de como resolver isso? Ou existe um modelo de interface do usuário melhor que devo olhar completamente?

Desde já, obrigado.

Foi útil?

Solução 2

Obrigado, Andrew, isso fez isso. A chave era que eu tinha que criar um datacontext separado para o DockPanel em questão e, em seguida, vinculá -lo a uma nova instância do objeto de penhor criado mais alto no modelo.

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

Eu ainda precisava saber mais detalhes para configurar o objeto de penhor adequadamente, mas consegui obtê -los vinculando a propriedade de tag do botão ao datacontext de seu pai modelado:

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

E a partir daí, consegui lidar com o resto em código-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);
        }
    }

Muito obrigado - isso me apontou na direção certa.

Outras dicas

A maneira mais fácil de fazer isso é ter a classe que representa itens no seu ListBox Itens Source para ter todos os campos que você está referenciando no seu Datatemplate. Em seguida, no manipulador de botões, você pode acessar as novas informações de penhor usando o contexto de dados do botão.

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

        //do stuff with pledge
    }

Pode haver uma maneira de fazer isso sem que os campos modificados façam parte da classe que compõe o Itens Source para o ListBox (apenas aprendendo o WPF), mas isso funciona. Se isso não ajudar, olharei para trás mais tarde (para o trabalho agora).

De qualquer forma, trabalho incrível para fazer um aplicativo para sua igreja, parece muito bom.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top