Wpf datagrid: create DatagridNumericColumn in wpf

I have a requirement that I want to create a datagridcolumn that accepts only integer values ​​when the user enters something other than numbers that process the text field. I tried many web pages, I'm tired of them, I really appreciate that someone has help.

+7
c # validation wpf datagrid
source share
5 answers

Based on the @nit clause, you can create your own class derived from a DataGridTextColumn as follows:

 public class DataGridNumericColumn : DataGridTextColumn { protected override object PrepareCellForEdit(System.Windows.FrameworkElement editingElement, System.Windows.RoutedEventArgs editingEventArgs) { TextBox edit = editingElement as TextBox; edit.PreviewTextInput += OnPreviewTextInput; return base.PrepareCellForEdit(editingElement, editingEventArgs); } void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e) { try { Convert.ToInt32(e.Text); } catch { // Show some kind of error message if you want // Set handled to true e.Handled = true; } } } 

In the PrepareCellForEdit method , you register the OnPreviewTextInput method to edit the TextBox PreviewTextInput , where you check the numeric values.

In xaml you just use it:

  <DataGrid ItemsSource="{Binding SomeCollection}"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding NonNumericProperty}"/> <local:DataGridNumericColumn Binding="{Binding NumericProperty}"/> </DataGrid.Columns> </DataGrid> 

Hope this helps

+14
source share

If you do not want to show any validation errors and just want to block any nonzero value, you can create a DataGridTemplateColumn and use a TextBox in the CellEditingTemplate .

  <DataGridTemplateColumn Width="100*"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=NumericProperty}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <TextBox PreviewTextInput="TextBox_PreviewTextInput" Text="{Binding Path=NumericProperty}"/> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> 

and in the PreviewTextInput of the TextBox set e.Handled = true if the value is other than integer:

  private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { try { Convert.ToInt32(e.Text); } catch { e.Handled = true; } } 
+3
source share

I found a solution to the same problem here: the input restriction to cells on a DataGrid must be numeric. But the accepted answer did not work for me. The following has been done:

  • For a DataGrid add an event handler for PreparingForCellEdit .
  • In this event handler, enter EditingElement in the TextBox and add an event handler for PreviewTextInput in the TextBox .
  • In the PreviewTextInput event PreviewTextInput , the value e.Handled is set to thttps: //stackoverflow.com/rue if the entry should not be allowed.

The above steps work if the user clicks a cell to edit. However, if the cell is not in edit mode, the PreparingForCellEdit event will not be raised. To check in this case:

  • Add an event handler to the DataGrid for PreviewTextInput .
  • In this e.OriginalSource e.OriginalSource event handler (terminating if it is not a DataGridCell ), check the DataGridCell's IsEditing , and if the cell does not edit the e.Handled set at thttps: //stackoverflow.com/rue.

The effect of the above is that the user needs to click on the cell to edit its contents, and thus, the combination PreparingForCellEdit / PreviewTextInput above will be called for all changes in the contents of the cell.

+3
source share

Use TryParse instead, this helps to limit input values ​​to integers only.

  /// <summary> /// This class help to create data grid cell which only support interger numbers. /// </summary> public class DataGridNumericColumn : DataGridTextColumn { protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs) { TextBox edit = editingElement as TextBox; if (edit != null) edit.PreviewTextInput += OnPreviewTextInput; return base.PrepareCellForEdit(editingElement, editingEventArgs); } private void OnPreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e) { int value; if (!int.TryParse(e.Text, out value)) e.Handled = true; } } 
+1
source share

Just to continue @Omribitan's answer. Here is the solution with adding Paste guard data:

 public class NumericTextColumn : DataGridTextColumn { protected override object PrepareCellForEdit(FrameworkElement editingElement, RoutedEventArgs editingEventArgs) { var edit = editingElement as TextBox; edit.PreviewTextInput += Edit_PreviewTextInput; DataObject.AddPastingHandler(edit, OnPaste); return base.PrepareCellForEdit(editingElement, editingEventArgs); } private void OnPaste(object sender, DataObjectPastingEventArgs e) { var data = e.SourceDataObject.GetData(DataFormats.Text); if (!IsDataValid(data)) e.CancelCommand(); } private void Edit_PreviewTextInput(object sender, TextCompositionEventArgs e) { e.Handled = !IsDataValid(e.Text); } bool IsDataValid(object data) { try { Convert.ToInt32(data); return true; } catch { return false; } } } 
+1
source share

All Articles