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]}"

それはすべてうまくいきます、そして私はそれを理解しています。データグリッドで行われた変更が基礎となるデータベースに更新されるように、データバインディングを双方向にしたいと考えています。これを行う方法の 1 つは、変更された行の値を取得し、Update メソッドで tableadapter を使用して、基になるデータベース (おそらく SelectedCellsChanged イベントなど) に加えられた変更を書き戻すことです。ただし、WPF のコード ビハインドでセル値を取得するのは難しいため、このようなアプローチは実装が困難です (WPF フレームワークを使用する必要があるため、これは間違った方法であると理解しています。助けてください) )。

では、どうすれば双方向のデータバインディングを設定して作業を行うことができますか? 次のようなデータグリッドプロパティの設定について言及している人を見てきました。

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 - 行がフォーカスを失うまでデータセットが更新されない

これは難しい方法でしたが、経験があれば、より優れたコードを提供できます。data binding、datagrid、datagridtemplatecolumn、two-way binding、cellEditEnding などの用語を検索してみてください。

幸運を!

于 2012-08-28T18:25:46.600 に答える
0

OK、少し遅れました。私が望んでいた答えが得られたと思います。データグリッドはデータ テーブルにバインドされています (私の場合)。これは、選択したアイテム (おそらくユーザーがダブルクリックした行) を取得し、それをデータ行に変換してから、関心のあるフィールドを取得できることを意味します。

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 に答える