在不使用MVVM的情况下实现双向DataGrid数据绑定



我会尽可能清楚地说明这一点,但我非常清楚我可能问错了问题。我在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);

}

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

我希望这能帮助到别人!

相关内容

  • 没有找到相关文章

最新更新