gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 19:28:57 25 4
gpt4 key购买 nike

我目前正在学习 XAML 和 WPF,并且仍在掌握数据绑定(bind),大部分时间只是将头撞在墙上,直到它起作用为止。

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

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

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:导致错误的原因是什么?

数据网格 + 组合框显示正确,那么下面的 XAML 有什么问题?我看不到它!

我的(简单)测试项目设置并不奇怪:

  • VS2013、WPF、.NET45 + Entity Framework 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:有没有更好的方法来完成这一切?

我必须使用 DataSets、TableAdapters 和 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 中完成所有这些,无需任何代码,但到目前为止我还没有成功(绑定(bind)不正确?!)

如果有人可以向我展示更好的方法,或者改进上面的代码,我将不胜感激。

在使用 Ruby 多年之后,我最近又回到了 C#,现在 WPF/XAML 正在让我大吃一惊!

最佳答案

好的,回答我自己的问题(本来打算删除,但会保留它,以防它帮助其他人)。

现在看来,使用 tableadapter 是错误的方法。我确信它在 VS2012/EF5 及更早版本中工作得很好(不知道 - 没有测试过),但我就是无法让这个该死的东西在 VS2013+ 和 EF6+ 中正常工作,可能是因为我对它缺乏经验。

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

EF 网站入门部分的以下文章对此进行了介绍,但当时我没能发现它,即使它是大粗体!:

Databinding with WPF

此外,我还发现 PluralSight 上的以下类(class)非常有值(value):

WPF Databing in Depth - by Brian Noyes

所以,TLDR:

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

希望对某人有帮助!

关于WPF 绑定(bind)错误(System.Windows.Data 错误 : 17),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29070492/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com