2

私が自分の教会のためにデザインしている WPF ページでは、2 つの Linq-to-Entities クエリの結果にバインドされた 2 つの ListBox コントロールがあります。 2 番目のリストボックス/クエリには、誓約したすべての人々 (および関連する誓約) が含まれます。具体的には:

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

アプリケーションのユーザーが最初の ListBox から家族を選択すると、ListBox 項目がわずかに拡大して誓約のフィールドが表示されるため、誓約の詳細を 2 番目の ListBox に簡単に追加できます。次のようになります。

http://wouldbetheologian.com/images/PledgeManager.jpg (オフサイト画像)

基盤となるデータベースには、「Pledge」テーブルと 1 対多の関係を持つ「Family」テーブルがあります。ユーザーが [誓約を追加] ボタンをクリックすると、新しい誓約インスタンスを作成してデータベースに保存し、2 つのコントロールを更新します。

しかし、私はそれを行う方法を理解できません。コード ビハインドで実行しようとすると、(n インスタンスの) [誓約を追加] ボタンのイベント ハンドラーが問題のコントロールを参照できるようには見えません。XAML で、ListBoxItem DataTemplate コントロールを Family.Pledge (または Family.Pledge.FirstOrDefault()) フィールドにバインドしようとすると、Add のイベント ハンドラーで現在の Family オブジェクトを見ると、これらのフィールドはまだ空です。誓約ボタン。

これを解決する方法について何か考えはありますか?それとも、私が全体的に見るべきより良いUIモデルはありますか?

前もって感謝します。

4

2 に答える 2

2

ありがとう、アンドリュー。重要なのは、問題の DockPanel 用に個別の DataContext を作成し、それをテンプレートの上位に作成された Pledge オブジェクトの新しいインスタンスにバインドする必要があるということでした。

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

Pledge オブジェクトを適切に設定するには、さらに詳細を知る必要がありましたが、ボタンの Tag プロパティをテンプレート化された親の DataContext にバインドすることで、それらを取得することができました。

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

そこから、コード ビハインドで残りを処理することができました。

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

多くの感謝 - それは私を正しい方向に向けました。

于 2009-03-03T09:48:42.267 に答える
2

これを行う最も簡単な方法は、ListBox ItemsSource 内のアイテムを表すクラスを用意して、DataTemplate で参照しているすべてのフィールドを持たせることです。次に、ボタン ハンドラーで、ボタンのデータ コンテキストを使用して、新しい誓約情報にアクセスできます。

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

        //do stuff with pledge
    }

テンプレート化されたフィールドを ListBox の ItemsSource を構成するクラスの一部にせずにこれを行う方法があるかもしれませんが (WPF を自分で学習するだけです)、これは機能します。それでも問題が解決しない場合は、後で振り返ります (今は仕事に出かけます)。

とにかく、あなたの教会のためのアプリを作る素晴らしい仕事です。かなり良さそうです。

于 2009-03-03T07:05:15.123 に答える