WPF绑定错误(System.Windows.Data错误:17)

4

我正在学习XAML和WPF,并且仍在努力理解数据绑定,大部分时间都在摸索直到它起作用。

我正在使用组合框来查找“siteid”和“roleid”的相应表的“name”值,同时在DataGrid中显示用户表。

表单如预期地工作,即以正确的方式显示了带有组合框的datagrid,并且也成功更新了用户记录,但是我在输出窗口中获得以下错误消息,这让我感到疯狂:

System.Windows.Data Error: 17 : Cannot get 'Name' value (type 'String') from '' (type 'DataRowView'). BindingExpression:Path=Name; DataItem='DataRowView' (HashCode=25172842); target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object') RowNotInTableException:'System.Data.RowNotInTableException: This row has been removed from a table and does not have any data. BeginEdit() will allow creation of new data in this row.

问题1:导致此错误的原因是什么?

datagrid+组合框正确显示,那么下面的XAML哪里出错了呢?我看不出来!

我的(简单)测试项目设置并没有什么特别之处:

  • VS2013、WPF、.NET45 + entity framework6.1.3(最新版本)和SQL2012
  • 用户表:ID(pk)、用户名、密码、SiteID(FK)、RoleID(FK)
  • sites表:ID(pk)、名称、描述
  • roles表:ID(pk)、名称、描述

XAML:

    <UserControl.Resources>
        <local:TestProjectDataSet x:Key="testProjectDataSet"/>

        <CollectionViewSource x:Key="usersViewSource" Source="{Binding Users, Source={StaticResource testProjectDataSet}}"/>
        <CollectionViewSource x:Key="rolesViewSource" Source="{Binding Roles, Source={StaticResource testProjectDataSet}}"/>
        <CollectionViewSource x:Key="sitesViewSource" Source="{Binding Sites, Source={StaticResource testProjectDataSet}}"/>

    </UserControl.Resources>

    <Grid Style="{StaticResource ContentRoot}" DataContext="{StaticResource usersViewSource}">
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>

        <TextBlock Text="User Management:" Style="{StaticResource Heading2}" Grid.Row="0"/>

        <DataGrid x:Name="UsersDataGrid" ItemsSource="{Binding}" EnableRowVirtualization="True" Grid.Row="1" RowDetailsVisibilityMode="VisibleWhenSelected" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="idColumn" Width="SizeToHeader" IsReadOnly="True" Header="Id" Binding="{Binding Id}" />

                <DataGridTextColumn x:Name="usernameColumn" Width="Auto" Header="Username" Binding="{Binding Username}"/>

                <DataGridTextColumn x:Name="passwordColumn" Width="Auto" Header="Password" />

                <DataGridTemplateColumn x:Name="siteNameColumn" Header="Site" Width="Auto">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox IsSynchronizedWithCurrentItem="False"
                                      ItemsSource="{Binding Source={StaticResource sitesViewSource}}"
                                      DisplayMemberPath="Code"
                                      SelectedValuePath="Id"
                                      SelectedValue="{Binding SiteId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                      />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <DataGridTemplateColumn x:Name="roleNameColumn" Header="Role" Width="Auto">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox IsSynchronizedWithCurrentItem="False"
                                      ItemsSource="{Binding Source={StaticResource rolesViewSource}}" 
                                      DisplayMemberPath="Name"
                                      SelectedValuePath="Id"
                                      SelectedValue="{Binding RoleId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                      />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

        <Button Content="Save" Width="100" Height="50" Click="Button_Click" Grid.Row="2" />

    </Grid>

</UserControl>

问题2:有更好的方法来完成所有这些吗?

我必须使用数据集、表适配器和CollectionViewSources以及一些代码后台。

using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace TestProjectUI.Pages.Admin
{
    /// <summary>
    /// Interaction logic for ManageUsersPage.xaml
    /// </summary>
    public partial class ManageUsersPage : UserControl
    {
        private TestProjectDataSet _database;

        private TestProjectDataSetTableAdapters.UsersTableAdapter _usersAdapter;
        private TestProjectDataSetTableAdapters.RolesTableAdapter _rolesAdapter;
        private TestProjectDataSetTableAdapters.SitesTableAdapter _sitesAdapter;

        private CollectionViewSource _usersViewSource;
        private CollectionViewSource _rolesViewSource;
        private CollectionViewSource _sitesViewSource;

        public ManageUsersPage()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            _database = ((TestProjectDataSet)(FindResource("magazineInventoryDataSet")));

            _usersAdapter = new TestProjectDataSetTableAdapters.UsersTableAdapter();
            _usersAdapter.Fill(_database.Users);
            _usersViewSource = ((CollectionViewSource)(FindResource("usersViewSource")));
            _usersViewSource.View.MoveCurrentToFirst();

            _rolesAdapter = new TestProjectDataSetTableAdapters.RolesTableAdapter();
            _rolesAdapter.Fill(_database.Roles);
            _rolesViewSource = ((CollectionViewSource)(FindResource("rolesViewSource")));
            _rolesViewSource.View.MoveCurrentToFirst();

            _sitesAdapter = new TestProjectDataSetTableAdapters.SitesTableAdapter();
            _sitesAdapter.Fill(_database.Sites);
            _sitesViewSource = ((CollectionViewSource)(FindResource("sitesViewSource")));
            _sitesViewSource.View.MoveCurrentToFirst();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            _usersAdapter.Update(_database.Users);
        }

    }
}

我曾以为可以在纯XAML中完成所有这些而不需要后台的代码,但迄今为止我还没有成功实现(绑定错误?!)。
如果有人能展示一个更好的方法或改进上述代码,我将不胜感激。
最近我又回到了C#,经过多年的Ruby之后,现在WPF/XAML让我感到很棘手!
1个回答

3

好的,我回答我自己的问题(本来想删除,但现在将其保留以帮助其他人)。

现在似乎使用tableadapter是错误的方法。 我相信在VS2012 / EF5及更早版本中它可以正常工作(不确定-没有测试),但我只是不能在VS2013+&EF6+中正确地使用它,可能是由于我的经验不足。

无论如何,推荐的方法是在设置数据源时使用“对象”。 将这些对象数据源拖到表单上时,数据绑定完美地工作。 创建主/细节表单或查找组合框非常简单。

这在EF网站的入门部分的以下文章中有所涉及,但我当时没能发现它,尽管它是用大号粗体字写的!:

WPF数据绑定

此外,我还发现PluralSight上的以下课程非常有价值:

深入学习WPF数据绑定 - 作者Brian Noyes

简而言之:

1)在创建数据源时使用“Object”(在VS2013+和EF6+中),不要使用“Database” 2)仔细阅读任何入门文章:D

希望对某些人有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接