2

我会尽可能清楚地说明这一点,但我很清楚我可能问错了问题。我在 WPF (.NET 4.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 方法的 tableadapter 将所做的任何更改写回底层数据库(可能是在 SelectedCellsChanged 事件或类似事件上)。但是,任何这样的方法都很难实现,因为在 WPF 的代码隐藏中获取单元格值很困难(我的理解是这是错误的方法,因为我应该使用 WPF 框架,所以请帮助我)。

那么......我如何设置双向数据绑定来为我完成工作?我见过人们提到设置 datagrid 属性,例如:

SelectedItem="{Binding Path=SelectedIndex,Mode=TwoWay}"

但我不明白如何让它与数据适配器和数据集一起使用。我不想要任何涉及 MVVM 或模型的解决方案,因为我没有使用这些(是的,我可能应该使用,我知道)。我还想避免大量复杂的 C# 代码,包括可观察的集合、通过控制层次结构递归搜索以查找父对象等。

我已经搜索了很长时间,我认为我所要求的确实存在 - 如果不存在,请告诉我它不存在,并为浪费您的时间道歉,温柔的读者!

4

2 回答 2

0

我完全不明白你。您希望避免使用 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 - 数据集不更新直到行失去焦点

这是一个艰难的方法,但如果你有经验,你可以提供更好的代码。尝试搜索术语数据绑定、datagrid、datagridtemplatecolumn、双向绑定、cellEditEnding。

祝你好运!

于 2012-08-28T18:25:46.600 回答
0

好的,有点晚了,我想我有我想要的答案。数据网格绑定到数据表(在我的实例中)。这意味着您可以获取所选项目(可能是用户双击的行),将其转换为数据行,然后获取您感兴趣的字段。

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);

}

这将解决双击数据网格中的一行的问题,这就是我的想法。如果您正在使用类,则可以将所选项目转换为相关对象,并获取其属性。

我希望这可以帮助别人!

于 2012-09-13T12:49:43.157 回答