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

时间:2015-03-16 06:05:32

标签: wpf xaml

我目前正在学习XAML& WPF并且仍在掌握数据绑定,大多只是将我的头撞在墙上直到它工作。

我在DataGrid中显示users表,并使用组合框查找' name'来自' siteid'的相应表格中的值和' roleid'值。

表单按预期工作,即它显示正确设置了组合框的数据网格 - 它也更新了用户记录 - 但是我在输出窗口中收到以下错误消息并且它让我疯狂:

  

System.Windows.Data错误:17:无法获取'姓名'来自''的值(类型'字符串') (键入' DataRowView')。 BindingExpression:路径=名称;的DataItem =' DataRowView的' (的HashCode = 25172842);目标元素是' ComboBox' (名称='&#39);目标财产是“NoTarget' (类型'对象')RowNotInTableException:' System.Data.RowNotInTableException:此行已从表中删除,并且没有任何数据。 BeginEdit()将允许在此行中创建新数据。

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

datagrid + comboboxes正确显示所以下面的XAML出了什么问题?我看不到它!

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

  • VS2013,WPF,.NET45 +实体框架6.1.3(最新)& SQL2012
  • 用户表:ID(pk),用户名,密码,SiteID(Fk),RoleID(Fk)
  • 网站表:ID(pk),名称,说明
  • 角色表: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:有没有更好的方法来完成所有这些?

我不得不使用DataSet,TableAdapters&amp; 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 个答案:

答案 0 :(得分:3)

好的,回答我自己的问题(打算删除,但不会让它帮助别人出去)。

现在似乎使用tableadapter是错误的做法。我确信它在VS2012 / EF5及更早版本中运行得很好(不知道 - 未经过测试),但我无法在VS2013 +&amp; amp; EF6 +,可能是由于我缺乏经验。

无论如何,推荐的方法是使用&#39;对象&#39;在设置数据源时。将这些对象数据源拖动到表单上时,数据绑定非常有效。创建主/明细表单或查找组合非常容易。

EF网站的“入门”部分中的以下文章对此进行了介绍,但当时我没有发现它,即使它是一个粗体字体!:

Databinding with WPF

此外,我还发现以下关于PluralSight EXTREMELY极具价值的课程:

WPF Databing in Depth - by Brian Noyes

所以,TLDR:

1)使用&#39;对象&#39;在创建数据源时(在VS2013 +&amp; EF6 +中) - 不要使用&#39;数据库&#39; 2)仔细阅读任何入门文章:D

希望能帮助别人!