WPF DataTemplateでコントロールを参照する
-
03-07-2019 - |
質問
教会用に設計している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 (オフサイト画像)
(特に)基礎となるデータベースには「家族」があります。 「誓約」と1対多の関係を持つ表表。ユーザーが[誓約を追加]をクリックすると、ボタン、新しいPledgeインスタンスを作成し、データベースに保存してから、2つのコントロールを更新します。
しかし、私はそれを行う方法を理解できません。コードビハインドでこれを実行しようとすると、(nインスタンスの)" Add Pledge"のイベントハンドラーのように見えません。ボタンは問題のコントロールを参照できます。 XAMLで、ListBoxItem DataTemplateコントロールをFamily.Pledge(またはFamily.Pledge.FirstOrDefault())フィールドにバインドしようとすると、追加のイベントハンドラーで現在のFamilyオブジェクトを見ると、それらのフィールドはまだ空です誓約ボタン。
これを解決する方法についての考えはありますか?それとも、私が一緒に見るべきより良いUIモデルがありますか?
事前に感謝します。
解決 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オブジェクトを適切に設定するには、さらに詳細を知る必要がありましたが、Buttonの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);
}
}
多くの感謝-それは私を正しい方向に向けました。
他のヒント
それを行う最も簡単な方法は、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を学習するだけですが)、これは機能します。それでも解決しない場合は、後で振り返ります(今すぐ仕事に取り掛かります)。
とにかく、あなたの教会のためのアプリを作るのは素晴らしい仕事です。