我会尽可能清楚地说明这一点,但我非常清楚我可能问错了问题。我在WPF(.NET4.0)中有一个datagrd,我将其绑定到数据集中的数据表。后面的相关代码(在窗口加载时运行)是:
// create a connection to Top Trumps database
String cs = ConfigurationManager.ConnectionStrings["csTopTrumps"].ConnectionString;
SqlConnection cn = new SqlConnection(cs);
// create a new dataset
DataSet ds = new DataSet();
// open the connection (not strictly necessary, as the
// data adapter will do this when you use it anyway)
cn.Open();
// fill data table called Cards with contents of tblCard
SqlDataAdapter daCards = new SqlDataAdapter();
daCards.SelectCommand =
new SqlCommand("SELECT * FROM tblCard ORDER BY CardTitle", cn);
daCards.Fill(ds, "Cards");
// now set the data context for the entire window
this.DataContext = ds;
我的数据网格定义开始了:
<DataGrid ItemsSource="{Binding Tables[Cards]}"
所有这些都很好,我理解。我现在想让数据绑定双向进行,这样在数据网格中所做的更改就会更新回底层数据库。我知道我可以做到这一点的一种方法是获取更改行的值,并使用带有Update方法的表适配器将所做的任何更改写回底层数据库(可能是在SelectedCellsChanged事件或类似事件上)。然而,任何这样的方法都很难实现,因为在WPF中获取代码背后的单元格值是很困难的(我的理解是,这是错误的做法,因为我应该使用WPF框架,所以请帮助我)。
所以。。。我如何设置双向数据绑定来为我做这项工作?我见过有人提到设置数据网格属性,比如:
SelectedItem="{Binding Path=SelectedIndex,Mode=TwoWay}"
但我不明白如何将其用于数据适配器和数据集。我不想要任何涉及MVVM或模型的解决方案,因为我没有使用这些(是的,我知道我可能应该使用)。我还想避免大量复杂的C#代码,包括可观察的集合、通过控制层次结构进行递归搜索以找到父级等等。
我已经搜索了很长时间,我想我所问的确实存在——如果不存在,请告诉我它不存在,并为浪费你的时间道歉,温柔的读者!
我很不理解你。您希望避免使用WPF框架(可观察的集合、绑定、递归搜索等),但希望找到一种使用WPF架构的方法。
首先你需要这些功能:
public static T GetVisualChild<T>(Visual parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
public static DataGridRow GetSelectedRow(this DataGrid grid)
{
return (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(grid.SelectedItem);
}
public static DataGridRow GetRow(this DataGrid grid, int index)
{
DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
if (row == null)
{
// May be virtualized, bring into view and try again.
grid.UpdateLayout();
grid.ScrollIntoView(grid.Items[index]);
row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
}
return row;
}
public static DataGridCell GetCell(this DataGrid grid, DataGridRow row, int column)
{
if (row != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row);
if (presenter == null)
{
grid.ScrollIntoView(row, grid.Columns[column]);
presenter = GetVisualChild<DataGridCellsPresenter>(row);
}
DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
return cell;
}
return null;
}
public static DataGridCell GetCell(this DataGrid grid, int row, int column)
{
DataGridRow rowContainer = grid.GetRow(row);
return grid.GetCell(rowContainer, column);
}
现在DataGrid实际上有几乎有用的事件。它叫做CellEditEnding。连接
private bool isManualEditCommit;
private void yourHandler(
object sender, DataGridCellEditEndingEventArgs e)
{
if (!isManualEditCommit)
{
isManualEditCommit = true;
DataGrid grid = (DataGrid)sender;
grid.CommitEdit(DataGridEditingUnit.Row, true);
isManualEditCommit = false;
} else {
/* you can write foreach loop that would loop through all the DataGridCells
with DataGridCell cell = grid.GetCell(row, col),
you can recieve value like GetVisualChild<TextBlock>(cell).Text
and update everything when you're at last value */
}
}
也请阅读这篇文章;WPF DataGrid CellEditEnding-数据集不更新,直到行失去焦点
这是一条艰难的道路,但如果你有经验,你可以提供更好的代码。尝试搜索术语数据绑定、数据网格、数据网格模板列、双向绑定、cellEditEnding。
祝你好运!
好吧,有点晚了,我想我已经得到了我想要的答案。数据网格绑定到一个数据表(在我的实例中)。这意味着您可以访问所选项目(可能是用户双击的行),将其转换为数据行,然后访问您感兴趣的字段。
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
// turn the datagrid selected "item" into a data row
DataRowView dr = dg.SelectedItem as DataRowView;
// get at the value for any field (here it's the one called CARD) in the underlying datatable
string CardTitle = (string)dr["Card"];
// display it ...
MessageBox.Show("You are on card " + CardTitle);
}
这将解决双击数据网格中的一行的问题,这也是我的想法。如果使用类,则可以将所选项强制转换为相关对象,并获取其属性。
我希望这能帮助到别人!