2013-10-15 4 views
7

У меня есть требование, чтобы я хотел создать datagridcolumn, который принимает только числовые значения (integer), когда пользователь вводит что-то другое, кроме чисел, обрабатывающих текстовое поле. Я пробовал много веб-страниц, я устал от них, я очень признателен, что у кого-то есть помощь.wpf datagrid: создать DatagridNumericColumn в wpf

+0

Вы можете создать свой собственный класс, производный от 'DataGridColumn' и преформ цифровой проверки там .. –

+0

@Omribitan, если у вас есть какие-либо примеры, вы опубликуете ссылку, это будет отличная помощь для меня – Mussammil

ответ

14

основе @nit предложение, вы можете создать свой собственный класс, производный от DataGridTextColumn так:

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

В методе PrepareCellForEdit вы регистрируете метод OnPreviewTextInput на редактирование TextBoxPreviewTextInput событие, в котором вы проверяете числовые значения.

В XAML, вы просто использовать:

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

Надеется, что это помогает

+1

его работающий друг спасибо – Mussammil

3

Если вы не хотите показывать какие-либо ошибки проверки и хотите заблокировать любое значение, отличное от числа, то вы можете создать DataGridTemplateColumn и в CellEditingTemplate использовать TextBox.

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

и PreviewTextInput в TextBox установлен e.Handled = true если значение кроме целого числа:

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

спасибо, но на самом деле я не могу использовать DataGridTemplateColumn в своем запросе – Mussammil

3

Я получил сюда в поиски решения тех же задачи: сдерживая вход в клетки на DataGrid быть числовыми. Но принятый ответ не сработал для меня. Следующее сделал:

  1. Для DataGrid добавить обработчик событий для PreparingForCellEdit.
  2. В этом случае обработчик, нанесите EditingElement на TextBox и добавьте обработчик события для PreviewTextInput в TextBox.
  3. В обработчике событий PreviewTextInput установлен e.Handled в true, если вход не допускается.

Вышеуказанные шаги работают, если пользователь нажимает на ячейку для редактирования. Однако, если ячейка не находится в режиме редактирования, событие PreparingForCellEdit не будет вызываться. Для выполнения проверки в этом случае:

  1. Добавление обработчика событий в DataGrid для PreviewTextInput.
  2. В этом обработчике событий, смело отбрасывать e.OriginalSource к DataGridCell (выходу, если это не DataGridCell), проверьте свойство DataGridCell'sIsEditing, и если ячейка не редактирование установить e.Handled истину.

Эффект выше является то, что пользователь должен нажать на ячейку, чтобы отредактировать его содержимое и, таким образом, сочетание PreparingForCellEdit/PreviewTextInput выше будет вызываться для всех изменений содержимого ячейки.

1

Вместо этого используйте TryParse, это помогает ограничить входные значения только целыми числами.

/// <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

Просто продлить @ ответ Omribitan, вот это решение с данными Paste добавил охранник:

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