2013-09-27 2 views
0

У меня есть этот код XAML для acolumn в DataGridWPF числовой формат

<DataGridTemplateColumn Header="% Deduccion Anticipo"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding NumPorcentajeAnticipo, Mode=TwoWay, StringFormat={}{0:00.}%}" Visibility="{Binding Merlin_ConceptosFacturacion.BitOtrosItms_Anticipos,Converter={StaticResource boolToVisibility}}"/> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
    <DataGridTemplateColumn.CellEditingTemplate> 
     <DataTemplate> 
      <TextBox Text="{Binding NumPorcentajeAnticipo, Mode=TwoWay,StringFormat={}{0:00.}%}" Visibility="{Binding Merlin_ConceptosFacturacion.BitOtrosItms_Anticipos,Converter={StaticResource boolToVisibility}}"/> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellEditingTemplate> 
</DataGridTemplateColumn> 

StringFormat в своей работе применяет, как я ожидал, но проблема Мюи это пользователь может заполнить его с любой символ альфа, символ числа, как я могу сделать, чтобы предотвратить его, можно установить маску ввода?

Я пытаюсь использовать другой StringFormats, но любой из них работает так, как я ожидаю.

UPDATE: столбец в настоящее время привязан к цифровому свойству моей модели просмотра.

ответ

0

После некоторых исследований нашел это на другой вопрос:

Числовой ввод данных в WPF И @Brian Hinchey answer матч с некоторыми из моих потребностей.

Просто добавьте меня некоторые валидации культуры для десятичные числа плюс некоторые инструменты для редактирования и проверки. Надеюсь, это поможет кому-то другому.

Чтобы использовать его:

<DataGridTemplateColumn.CellEditingTemplate> 
    <DataTemplate> 
     <controls:NumericTextBox DecimalPlaces="2" DecimalSeparator="."/> 
    </DataTemplate> 
</DataGridTemplateColumn.CellEditingTemplate> 

Если нет знаков после запятой или разделитель не предусмотрено, оно принимает CultureInfo.CurrentCulture Parms

Вот окончательный код: не

public class NumericTextBox : TextBox 
{ 
    #region Formato 
    private string previousText = ""; 
    private bool ApplyingFormat = false; 
    private CultureInfo _CI = new CultureInfo(CultureInfo.CurrentCulture.LCID,true); 
    public CultureInfo CI 
    { 
     get { return _CI; } 
     set { _CI = value; } 
    } 

    private int _DecimalPlaces = 0; 
    /// <summary> 
    /// Numero de plazas decimales 
    /// </summary> 
    public int DecimalPlaces 
    { 
     get { return _DecimalPlaces; } 
     set { _DecimalPlaces = value; _CI.NumberFormat.NumberDecimalDigits = value; } 
    } 
    public Decimal DecimalValue = 0; 

    private string _DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; 
    public string DecimalSeparator 
    { 
     get { return _DecimalSeparator; } 
     set { _DecimalSeparator = value; _CI.NumberFormat.NumberDecimalSeparator = _DecimalSeparator; } 
    } 

    //public string DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator; 
    #endregion 


    public NumericTextBox() 
    { 
     HorizontalContentAlignment = HorizontalAlignment.Right; 
     DataObject.AddPastingHandler(this, OnPaste); 
    } 

    private void OnPaste(object sender, DataObjectPastingEventArgs dataObjectPastingEventArgs) 
    { 
     var isText = dataObjectPastingEventArgs.SourceDataObject.GetDataPresent(System.Windows.DataFormats.Text, true); 
     if (isText) 
     { 
      var text = dataObjectPastingEventArgs.SourceDataObject.GetData(DataFormats.Text) as string; 
      if (IsTextValid(text)) 
      { 
       return; 
      } 
     } 
     dataObjectPastingEventArgs.CancelCommand(); 
    } 

    private bool IsTextValid(string enteredText) 
    { 
     // If keyboard insert key is in toggled mode, and the actual insert point is Decimalseparator, we must avoid to overwrite it 
     if (SelectionStart == this.Text.IndexOf(DecimalSeparator) 
      & System.Windows.Input.Keyboard.GetKeyStates(System.Windows.Input.Key.Insert) == System.Windows.Input.KeyStates.Toggled) 
     { 
      SelectionStart += 1; 
     } 

     if (!enteredText.All(c => Char.IsNumber(c) || c == DecimalSeparator.ToCharArray()[0] || c == '-')) 
     { 
      return false; 
     } 

     //We only validation against unselected text since the selected text will be replaced by the entered text 
     var unselectedText = this.Text.Remove(SelectionStart, SelectionLength); 
     if (enteredText == DecimalSeparator && unselectedText.Contains(DecimalSeparator)) 
     { 
      // Before return false, must move cursor beside Decimal separator 
      SelectionStart = this.Text.IndexOf(DecimalSeparator) + 1; 
      return false; 
     } 

     if (enteredText == "-" && unselectedText.Length > 0) 
     { 
      return false; 
     } 

     return true; 
    } 

    private bool ApplyFormat(TextChangedEventArgs e) 
    { 
     if (!ApplyingFormat) 
     { 
      ApplyingFormat = true; 
      int SelectionStartActual = SelectionStart; 
      string FinallText = this.Text; 
      if (!FinallText.Contains(DecimalSeparator) & DecimalPlaces > 0) 
      { 
       FinallText = String.Format("{0}{1}{2}", this.Text, DecimalSeparator, new string('0', DecimalPlaces)); 
      } 
      bool state = Decimal.TryParse(FinallText, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint | NumberStyles.AllowTrailingSign, _CI, out DecimalValue); 
      DecimalValue = Math.Round(DecimalValue, DecimalPlaces); 
      if (DecimalValue == 0) 
      { 
       FinallText = ""; 
      } 
      else 
      { 
       if (FinallText != DecimalValue.ToString(_CI)) 
       { 
        FinallText = DecimalValue.ToString(_CI); 
       } 
      } 
      if (FinallText != this.Text) 
      { 
       this.Text = FinallText; 
       SelectionStart = SelectionStartActual; 
      } 

      previousText = this.Text; 

      ApplyingFormat = false; 
      return state; 
     } 
     else 
     { 
      return true; 
     } 
    } 

    protected override void OnTextChanged(TextChangedEventArgs e) 
    { 
     e.Handled = !ApplyFormat(e); 
     base.OnTextChanged(e); 
    } 

    protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e) 
    { 
     e.Handled = !IsTextValid(e.Text); 
     base.OnPreviewTextInput(e); 
    } 
} 
0

Ни один из встроенных элементов управления не может указать маску ввода. Но в WPF есть маскированные входные элементы управления в Интернете. Мы используем Telerik Rad Controls для пакета WPF, и у него есть такой контроль. Я использую его в своем приложении, и он работает очень хорошо.

+1

Там действительно нет необходимости * купить * сторонний контроль, довольно тривиально достичь того, чего хочет OP, перехватывая нажатия клавиш - неважно, хорошая идея - это отдельный вопрос. –

+0

Tks для вашего ответа, из-за это очень распространенная вещь, которую я ожидал от родной WPF, имеет эту функцию. –

+0

@MattBurland: Правда. Однако, построить его самостоятельно означает отладить его самостоятельно. Третий сторонний контроль будет уже протестирован и отлажен. Хотя это не означает, что все ошибки были удалены. JuanPabloGomez: Я не верю, что в WinForms также доступны маскированные элементы управления вводом. –

1

Вы можете использовать событие KeyDownTextBox, чтобы перехватить и отфильтровать недопустимые значения. Вы могли бы даже создать свой собственный производный TextBox и переопределить OnKeyDown для лучшего инкапсулированного решения.

0

вы можете достичь своего требования, используя следующие методы.

  1. Поместите маскированное текстовое поле в CellEditingTemplate и установите маску в этом скрытом текстовом поле.
  2. Создайте пользовательский рендер на основе вашего требования и привяжите его к CellEditingTemplate.
Смежные вопросы