More DataGrid Samples: Custom Sorting, Drag and Drop of rows, Column Selection, and Single-click Editing


Jossef just wrote this great post on improving sorting in the DataGrid through a custom sort.  Check it out here.


Ben Carter also added another sample that includes row drag-and-drop and column selection through cell selection.  You can download that sample here.


One way to get single-click editing to work is to hack into one of the entry points for openning a cell/row for edit.  Cells from all DataGridColumn types can be openned for edit by pressing F2 on a selected cell, double-clicking a cell that has not been selected, typing in a selected cell, or clicking on a cell that is already selected.  An easy way to enable editing on a single-click is to catch the preview to the first mouse click of a cell and set it as selected.  Then when the DataGridCell.OnAnyMouseLeftButtonDown is called it will see that the cell has already been selected so this click will open the cell for edit.  Here is the code for it:


private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{


  DataGridCell cell = sender as DataGridCell;


  if (!cell.IsEditing)


  {
    // enables editing on single click


    if (!cell.IsFocused)


      cell.Focus();


    if (!cell.IsSelected)


      cell.IsSelected = true;
  }


}


 


                                 



<Style TargetType=”{x:Type dg:DataGridCell}”>


   <EventSetter Event=”PreviewMouseLeftButtonDown” Handler=”DataGridCell_PreviewMouseLeftButtonDown” />


</Style>

Comments (14)

  1. WAW says:

    When a new insert row is displayed is there a way to set the first cell or any cell in the new insertion row so the user can just start typing instead of having the user select the cell. What I’m trying to create is a easy way the the user to enter new data. Set the first cell in the insertion row in focus and ready for user input. The user then tabs to each blank cell enters data and when done press the return key. When the return key is press and the new insertion row is displayed I what to set focus to the first cell of the insertion row so the user can just continue to enter data. I’m maping the datagrid to a dataview so I get the event when a new row is entered into the dataview – return key pressed

    m_dvView[nDataViewIndex].Table.TableNewRow += EHTableNewRow;

  2. WAW,

    Here is one possible implementation for it.  You can listen for the PreviewKeyDown event then have a dispatcher operation call a delegate after the DataGrid.KeyDown method is complete.  Then after the operation you can update the current cell and focus.

    DataGrid_Standard.PreviewKeyDown += new KeyEventHandler(DataGrid_Standard_PreviewKeyDown);

    void DataGrid_Standard_PreviewKeyDown(object sender, KeyEventArgs e)

           {

               if (e.Key == Key.Enter)

               {

                   int i = 0;

                   foreach (object item in DataGrid_Standard.Items)

                   {

                       if (item == DataGrid_Standard.CurrentItem)

                       {

                           break;

                       }

                       i++;

                   }

                   DataGridRow row = GetRow(i);

                   if (row.IsEditing)

                       Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(OnKeyDown), new object[] { e });

               }

           }

    private object OnKeyDown(object arg)

           {

               object[] arguments = arg as object[];

               KeyEventArgs e = (KeyEventArgs)arguments[0];

               if (e.Key == Key.Enter)

               {

                   int i = 0;

                   foreach (object item in DataGrid_Standard.Items)

                   {

                       if (item == DataGrid_Standard.CurrentItem)

                       {

                           break;

                       }

                       i++;

                   }

                   DataGridCell cell = GetCell(i, 0);

                   if (DataGrid_Standard.SelectionUnit == DataGridSelectionUnit.Cell || DataGrid_Standard.SelectionUnit == DataGridSelectionUnit.CellOrRowHeader)

                   {

                       // have to deselect current cell(s)

                       DataGrid_Standard.SelectedCells.Clear();

                   }          

                   // set focus to the first cell

                   cell.Focus();

                   // select the first cell

                   cell.IsSelected = true;

                   // set the current cell to the first cell

                   DataGrid_Standard.CurrentCell = new DataGridCellInfo(DataGrid_Standard.CurrentItem, DataGrid_Standard.Columns[0]);

               }

               return null;

           }

  3. Overview The DataGrid uses a set of DataGridColumns to describe how to display its data just like a GridView

  4. If you haven’t already, you can download the binaries and source for the DataGrid here . DataGridComboBoxColumn

  5. PMN says:

    Thanks for all your help.

    Im having problems with single click edit on a DataGrid bound to a DataView. The problem occurs when navigating from a cell that is in edit mode to another cell on the same row.

    The call to ConvertCellInfoToIndexes fails (Call Stack: OnIsSelectedChanged -> CellIsSelectedChanged -> AddValidatedCell -> ConvertCellInfoToIndexes), rowIndex ends up being -1 due to the modified DataRowView not being found (having a different RowState I guess):

    rowIndex = _owner.Items.IndexOf(cell.Item)

    When I replace that code with a loop through the rows, they are matched correctly, this works:

    for (int i = 0; i < _owner.Items.Count; i++)

    {

    if (_owner.Items[i] == cell.Item)

           {

            rowIndex = i;

                   break;

    }

    }

    I also tried to force an EndEdit() on the underlying DataRow before trying to select the cell, but that made the insertion row to not showing up after edit is complete.

    This only occurs when binding to a DataTables DataView. Any ideas?

  6. PMN,

    This is a known issue and will be addressed in the final version of the WPF DataGrid.  Sorry for the inconvenience. = (

    Thanks,

    Vince

  7. WAW says:

    Thanks for the help

    where is GetCell and GetRow defined?

  8. WAW,

    These are defined by the app author.  Examples of them can be found on this thread, http://www.codeplex.com/wpf/Thread/View.aspx?ThreadId=34065

  9. As you might have heard, .NET Framework 3.5 SP1 and Visual Studio 2008 SP1 are out today! There are a

  10. In the v1 release (and CTP) of the WPF DataGrid there will be support for Clipboard.Copy but no support

  11. Here is a short sample on how to create a tri-state sorting experience with the WPF DataGrid . In the

  12. There have been several questions on the WPF CodePlex discussion list relating to styling rows and columns

  13. premasoft says:

    In WPF datagrid, I having problem to edit content in different cell than is focus. I can write data to the cell content and it is visible when the cell is not in editmode. But when user click in the cell and going to editmode the old value is back. I use IEnumerable datatable with LINQ to SQLClasses.

    The same problem are when this datarow have to be edit in own window for a singel row.

    I try to do this in code behind, but I cant find the way to do it.

    Is there any best practis for this?

Skip to main content