0

I have this XAML for acolumn into 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>

The Stringformat applys as i expect, but muy problem is the user can fill it with any char alpha, number symbol, how can i do to prevent it, it is posible set an inputmask ?

I'm was trying with another StringFormats but any one of them work as I expect.

UPDATE: The column is currently binded to a Numeric property of my view model.

4

4 回答 4

1

您可以使用 a 的KeyDown事件TextBox来拦截和过滤掉无效值。您甚至可以创建自己的派生TextBox和覆盖OnKeyDown,以获得更好的封装解决方案。

于 2013-09-27T17:46:03.670 回答
0

经过一些研究在另一个问题上发现了这一点:

WPF 中的数字数据输入@Brian Hinchey 的回答符合我的一些需求。

只需自己添加一些十进制数字的文化验证以及一些编辑和验证工具。希望这对其他人有帮助。

要使用它:

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

如果没有提供小数位或分隔符,则采用CultureInfo.CurrentCultureparms

这是最终代码:

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);
    }
}
于 2013-09-29T20:27:26.197 回答
0

None of the built-in controls have the ability to specify an input mask. But, there are masked input controls out there on the internet for WPF. We are using the Telerik Rad Controls for WPF package and it has such a control. I use it in my application and it works very well.

于 2013-09-27T17:30:01.257 回答
0

您可以使用以下方法实现您的要求。

  1. 将蒙版文本框放在 CellEditingTemplate 中,并在该蒙版文本框中设置蒙版。
  2. 根据您的要求创建自定义渲染并绑定到 CellEditingTemplate。
于 2013-09-28T03:52:15.550 回答