Подтвердить что ты не робот

Как отформатировать число десятичных знаков в wpf с помощью стиля/шаблона?

Я пишу программу WPF, и я пытаюсь определить способ форматирования данных в TextBox с помощью некоторого повторяемого метода, такого как стиль или шаблон. У меня много текстовых полей (точнее, 95), и каждый из них привязан к собственным числовым данным, каждый из которых может иметь свое собственное разрешение. Например, если данные 99.123 с разрешением 2, то он должен отображать 99.12. Аналогично, значение данных 99 и разрешение 3 должно отображаться как 99 000 (не 99). Есть ли способ сделать это?

Edit: Я должен уточнить, на текущем экране, на котором я работаю, есть 95 TextBoxes, но я хочу, чтобы каждый TextBox на разных экранах моей программы отображал правильное количество десятичных знаков. Теперь, когда я думаю об этом, некоторые из них - TextBoxes (например, экран, над которым я сейчас работаю), а некоторые - DataGrids или ListViews, но если я смогу понять, как заставить его работать в TextBoxes, я уверен, что смогу это также для других элементов управления.

В этом случае не так много кода, но я попытаюсь сделать его более ясным:

У меня есть модель просмотра, которая содержит следующие свойства (vb.net):

    Public ReadOnly Property Resolution As Integer
        Get
            Return _signal.DisplayResolution
        End Get
    End Property

    Public ReadOnly Property Value As Single
        Get
            Return Math.Round(_signal.DisplayValue, Resolution)
        End Get
    End Property

и в XAML у меня есть:

<UserControl.Resources>
    <vm:SignalViewModel x:Key="Signal" SignalPath="SomeSignal"/>
</UserControl.Resources>
<TextBox Grid.Column="3" IsEnabled="False" Text="{Binding Path=Value, Source={StaticResource Signal}, Mode=OneWay}" />

EDIT2 (мое решение): Оказалось, что, немного отодвинувшись от компьютера, я вернулся, чтобы найти простой ответ, который смотрел мне в лицо. Отформатируйте данные в модели просмотра!

    Public ReadOnly Property Value As String
        Get
            Return (Strings.FormatNumber(Math.Round(_signal.DisplayValue, _signal.DisplayResolution), _signal.DisplayResolution))
        End Get
    End Property
4b9b3361

Ответ 1

Вы должны использовать StringFormat в Binding. Вы можете использовать стандартные строковые форматы или пользовательские строковые форматы

<TextBox Text="{Binding Value, StringFormat=N2}" />
<TextBox Text="{Binding Value, StringFormat={}{0:#,#.00}}" />

Обратите внимание, что StringFormat работает только тогда, когда свойство target имеет строку типа. Если вы пытаетесь установить что-то вроде свойства Content (typeof(object)), вам нужно будет использовать пользовательский StringFormatConverter (как здесь) и передайте строку формата как ConverterParameter.

Изменить для обновленного вопроса

Итак, если ваш ViewModel определяет точность, я бы рекомендовал сделать это как MultiBinding и создать собственный IMultiValueConverter. На практике это довольно раздражает, чтобы перейти от простой привязки к той, которая должна быть расширена до MultiBinding, но если точность не известна во время компиляции, это в значительной степени все, что вы можете сделать. Ваш IMultiValueConverter должен будет принимать значение, а также точность и выводить форматированную строку. Вы могли бы сделать это, используя String.Format.

Однако для таких вещей, как ContentControl, вы можете гораздо проще сделать это с помощью Style:

<Style TargetType="{x:Type ContentControl}">
    <Setter Property="ContentStringFormat" 
            Value="{Binding Resolution, StringFormat=N{0}}" />
</Style>

Любой элемент управления, который предоставляет ContentStringFormat, можно использовать следующим образом. К сожалению, TextBox не имеет ничего подобного.

Ответ 2

Принятый ответ не показывает 0 в целочисленном месте при вводе, например, 0.299. Он показывает.3 в интерфейсе WPF. Поэтому мое предложение использовать следующий строковый формат

<TextBox Text="{Binding Value,  StringFormat={}{0:#,0.0}}" 

Ответ 3

    void NumericTextBoxInput(object sender, TextCompositionEventArgs e)
    {
        TextBox txt = (TextBox)sender;
        var regex = new Regex(@"^[0-9]*(?:\.[0-9]{0,1})?$");
        string str = txt.Text + e.Text.ToString();
        int cntPrc = 0;
        if (str.Contains('.'))
        {
            string[] tokens = str.Split('.');
            if (tokens.Count() > 0)
            {
                string result = tokens[1];
                char[] prc = result.ToCharArray();
                cntPrc = prc.Count();
            }
        }
        if (regex.IsMatch(e.Text) && !(e.Text == "." && ((TextBox)sender).Text.Contains(e.Text)) && (cntPrc < 3))
        {
            e.Handled = false;
        }
        else
        {
            e.Handled = true;
        }
    }