WPF数字格式

时间:2013-09-27 17:22:50

标签: c# wpf

我将这个XAML用于DataGrid的

<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适用于我所期望的,但muy问题是用户可以用任何char alpha填充它,数字符号,我该如何防止它,它是否设置了一个输入掩码?

我正在尝试使用另一个StringFormats但是其中任何一个都按照我的预期工作。

更新:该列当前绑定到我的视图模型的数字属性。

4 个答案:

答案 0 :(得分:1)

您可以使用TextBox的{​​{3}}事件拦截并过滤掉无效值。您甚至可以创建自己的派生TextBox并覆盖OnKeyDown以获得更好的封装解决方案。

答案 1 :(得分:0)

没有内置控件可以指定输入掩码。但是,互联网上有针对WPF的屏蔽输入控件。我们正在使用Telerik Rad Controls for WPF包,它有这样的控件。我在我的应用程序中使用它并且它运行良好。

答案 2 :(得分:0)

您可以使用以下方法达到您的要求。

  1. 将屏蔽的文本框放在CellEditingTemplate中,并在该屏蔽的文本框中设置遮罩。
  2. 根据您的要求创建自定义渲染并绑定到CellEditingTemplate。

答案 3 :(得分: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);
    }
}