在我为教会设计的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),但这是有效的。如果这没有帮助,我会稍后回顾(现在开始工作)。

无论如何,为你的教会做一个很棒的工作,看起来很不错。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top