引用WPF DataTemplate中的控件
-
03-07-2019 - |
题
在我为教会设计的WPF页面中,我有两个ListBox控件绑定到两个Linq-to-Entities查询的结果:第一个列表框/查询包含所有尚未承诺的人员年,第二个列表框/查询包含所有承诺的人(及其相关的承诺)。具体做法是:
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项会稍微扩展以显示一个pledge的字段,这样就可以很容易地将pledge详细信息添加到第二个ListBox中。它看起来像这样:
http://wouldbetheologian.com/images/PledgeManager.jpg (非现场图片)
底层数据库(以及其他内容)具有“家庭”数据库。与“承诺”的1:多关系的表格表。并且当用户点击“添加承诺”时按钮,我想创建新的Pledge实例,将其保存到数据库,然后刷新两个控件。
但我无法弄清楚如何做到这一点。如果我尝试在代码隐藏中执行它,它似乎不是(添加承诺)的“n实例”的事件处理程序。按钮可以引用有问题的控件;在XAML中,如果我尝试将ListBoxItem DataTemplate控件绑定到Family.Pledge(或Family.Pledge.FirstOrDefault())字段,当我在Add的事件处理程序中查看当前的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),但这是有效的。如果这没有帮助,我会稍后回顾(现在开始工作)。
无论如何,为你的教会做一个很棒的工作,看起来很不错。