스타일 / 템플릿을 사용하여 wpf에서 소수점 이하 자릿수를 포맷하는 방법은 무엇입니까?


94

WPF 프로그램을 작성 중이며 스타일이나 템플릿과 같은 반복 가능한 방법을 통해 TextBox의 데이터 서식을 지정하는 방법을 찾으려고합니다. 나는 많은 TextBoxes (정확히 95)를 가지고 있으며 각각은 자체 해상도를 정의 할 수있는 자체 숫자 데이터에 바인딩되어 있습니다. 예를 들어 데이터가 해상도가 2 인 99.123이면 99.12를 표시해야합니다. 마찬가지로 데이터 값 99와 해상도 3은 99.000 (99가 아님)으로 표시되어야합니다. 이를 수행하는 방법이 있습니까?

편집 : 작업중인 현재 화면에 95 개의 TextBox가 있지만 프로그램의 다양한 화면에있는 모든 TextBox가 올바른 소수 자릿수를 표시하기를 원합니다. 이제 생각해 보면이 중 일부는 TextBox (예 : 지금 작업중인 화면)이고 일부는 DataGrids 또는 ListViews이지만 TextBox에서 작동하는 방법을 알아낼 수 있다면 다른 컨트롤도 마찬가지입니다.

이 경우 공유 할 코드는 많지 않지만 더 명확하게 만들려고합니다.

다음 속성 (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

1
사용 IValueConverter? 실제 값과 해상도를 변환기에 전달하고 자체 내에서 반올림을 수행합니다. StringFormat이 95가 정확히 어떻게 TextBox생성 되는지 모른 채 a를 제안하기는 어렵습니다 .
Viv

현재 코드와 XAML을 게시합니다. 그렇지 않으면 모든 추측과 도움이되지 않는 추측입니다.
Federico Berasategui

나는 질문에 더 많은 정보를 추가하여 더 명확하게 만들었습니다.
AXG1010 2013-08-21

답변:


196

에서를 사용해야 StringFormat합니다 Binding. 표준 문자열 형식 또는 사용자 지정 문자열 형식을 사용할 수 있습니다 .

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

점을 유의 StringFormat대상 속성이 String 형의 경우에만 작동합니다. Content속성 ( typeof(object)) 과 같은 것을 설정하려는 경우 사용자 지정 StringFormatConverter( 여기와 같은 ) 을 사용하고 형식 문자열을 ConverterParameter.

업데이트 된 질문 수정

따라서 ViewModel정밀도를 정의하는 경우이 작업을으로 수행하고 MultiBinding직접 IMultiValueConverter. 이것은 실제로 간단한 바인딩에서으로 확장해야하는 바인딩으로 이동하는 데 매우 성가신 MultiBinding일이지만 컴파일 타임에 정밀도를 알 수없는 경우이 작업을 수행 할 수 있습니다. 귀하는 IMultiValueConverter값 및 정밀도, 출력 포맷 된 문자열을해야합니다. 을 사용하여이 작업을 수행 할 수 있습니다 String.Format.

그러나 a와 같은 경우 ContentControl에는 다음을 사용하여 훨씬 더 쉽게 수행 할 수 있습니다 Style.

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

a를 노출하는 모든 컨트롤은 ContentStringFormat이와 같이 사용할 수 있습니다. 불행히도 그런 TextBox것은 없습니다.


6
StringFormat이로 설정된 예제는 #,#.00컴파일되지 않습니다. 쉼표는 Binding태그 확장의 속성에 대한 구분 기호로 해석됩니다 .
Gigi 2014 년

@Gigi, 당신 말이 맞지만 다음과 같이 쉽게 사용할 수 있습니다 StringFormat={}{0:#,#.00}. 올바르게 작동하도록 답변을 업데이트하겠습니다.
Abe Heidebrecht 2014 년

'StringFormat = N {0}'은 훌륭하게 작동합니다. 정밀도가 2 인 경우 '10 .00 '을 제외하고 소수점 두 개를 표시하고 싶습니다.이 경우'10 '이 표시됩니다. 정밀도에 바인딩 할 때이를 수행하는 방법이 있습니까? 변환기를 사용해야 할 것 같습니다.
Gordon Slysz

.NET 문자열 형식을 사용하여 제시된 소수를 변경하는 방법이 없다고 생각하므로 변환기를 작성하는 것이 좋습니다.
Abe Heidebrecht

두 지정자 0 : #, #. 00을 사용하는 이유를 설명 할 수 있습니까? 둘 중 하나만으로는 충분하지 않습니까?
Lei Yang

7

받아 들여지는 대답은 0.299와 같은 입력을 할 때 정수 자리에 0을 표시하지 않습니다. WPF UI에 .3이 표시됩니다. 그래서 다음 문자열 형식을 사용하는 것이 좋습니다.

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

안녕하세요, 귀하의 솔루션은 괜찮지 만 오타 실수를 피하고 적어도 표시 방법을 확신하기 때문에 키워드 N1 (2,3 ...)을 사용하고 싶습니다. 그러나 실제로 두 번째 제안은 당신이 언급 한 것처럼 value <0이면 0을 표시하지 않습니다.
Kevin VDF

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

9
일부 설명은 답변의 질을 크게 향상시킬 수 있습니다.
mrun
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.