วิธีจัดรูปแบบจำนวนตำแหน่งทศนิยมใน wpf โดยใช้ style / template


94

ฉันกำลังเขียนโปรแกรม WPF และฉันพยายามหาวิธีจัดรูปแบบข้อมูลในกล่องข้อความด้วยวิธีการที่ทำซ้ำได้เช่นสไตล์หรือเทมเพลต ฉันมีกล่องข้อความจำนวนมาก (95 เป็นค่าที่แน่นอน) และแต่ละอันจะเชื่อมโยงกับข้อมูลตัวเลขของตัวเองซึ่งแต่ละอันสามารถกำหนดความละเอียดของตัวเองได้ ตัวอย่างเช่นหากข้อมูลเป็น 99.123 ที่มีความละเอียด 2 ข้อมูลก็ควรแสดงเป็น 99.12 ในทำนองเดียวกันค่าข้อมูล 99 และความละเอียด 3 ควรแสดงเป็น 99.000 (ไม่ใช่ 99) มีวิธีทำไหม?

แก้ไข: ฉันควรจะชี้แจงมีกล่องข้อความ 95 รายการบนหน้าจอปัจจุบันที่ฉันกำลังทำงานอยู่ แต่ฉันต้องการให้กล่องข้อความทุกชิ้นตลอดหน้าจอต่างๆในโปรแกรมของฉันแสดงจำนวนตำแหน่งทศนิยมที่ถูกต้อง ตอนนี้ฉันคิดเกี่ยวกับเรื่องนี้บางส่วนเป็น TextBoxes (เช่นหน้าจอที่ฉันกำลังทำงานอยู่ตอนนี้) และบางส่วนเป็น DataGrids หรือ ListViews แต่ถ้าฉันสามารถหาวิธีทำให้มันทำงานกับกล่องข้อความได้ฉันแน่ใจว่าฉันสามารถคิดได้ สำหรับการควบคุมอื่น ๆ ด้วย

ในกรณีนี้มีโค้ดไม่มากนัก แต่ฉันจะพยายามทำให้ชัดเจนขึ้น:

ฉันมี View Model ซึ่งมีคุณสมบัติดังต่อไปนี้ (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สร้างขึ้นได้อย่างไร
Viv

โพสต์รหัสปัจจุบันและ XAML มิฉะนั้นจะเป็นการคาดเดาและการคาดเดาที่ไม่เป็นประโยชน์
Federico Berasategui

ฉันได้เพิ่มข้อมูลเพิ่มเติมในคำถามซึ่งหวังว่าจะทำให้ชัดเจนขึ้น
AXG1010

คำตอบ:


198

คุณควรใช้StringFormatบนBinding. คุณสามารถใช้รูปแบบสตริงมาตรฐานหรือรูปแบบสตริงที่กำหนดเอง :

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

โปรดทราบว่าStringFormatจะใช้ได้เฉพาะเมื่อคุณสมบัติเป้าหมายเป็นสตริงชนิด หากคุณพยายามตั้งค่าบางอย่างเช่นContentคุณสมบัติ ( typeof(object)) คุณจะต้องใช้กำหนดเองStringFormatConverter( เช่นที่นี่ ) และส่งสตริงรูปแบบของคุณเป็นไฟล์ConverterParameter.

แก้ไขสำหรับคำถามที่อัปเดต

ดังนั้นถ้าคุณViewModelกำหนดความแม่นยำผมอยากแนะนำให้ทำเช่นนี้เป็นและการสร้างของคุณเองMultiBinding IMultiValueConverterสิ่งนี้ค่อนข้างน่ารำคาญในทางปฏิบัติโดยเปลี่ยนจากการผูกแบบธรรมดาไปเป็นแบบที่ต้องขยายออกไปเป็น a 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

@Gigi คุณพูดถูก แต่คุณสามารถใช้มันได้อย่างง่ายดาย: StringFormat={}{0:#,#.00}. ฉันจะอัปเดตคำตอบเพื่อให้ทำงานได้อย่างถูกต้อง
Abe Heidebrecht

'StringFormat = N {0}' ใช้งานได้ดี เพื่อความแม่นยำของ 2 ฉันต้องการให้แสดงทศนิยมสองตำแหน่งยกเว้น '10 .00 'ซึ่งในกรณีนี้ฉันต้องการให้แสดง' 10 ' มีวิธีทำอย่างไรเมื่อผูกเข้ากับความแม่นยำ? ดูเหมือนว่าฉันจะต้องใช้ตัวแปลง
Gordon Slysz

ฉันไม่คิดว่าจะมีวิธีเปลี่ยนทศนิยมที่นำเสนอโดยใช้รูปแบบสตริง. NET ดังนั้นคุณน่าจะดีกว่าที่จะเขียนตัวแปลง
Abe Heidebrecht

คุณอธิบายได้ไหมว่าทำไมใช้ตัวระบุ 2 ตัว 0: #, #. 00 แค่ตัวระบุเดียวไม่พอ
Lei Yang

7

คำตอบที่ยอมรับจะไม่แสดง 0 ในตำแหน่งจำนวนเต็มในการให้อินพุตเช่น 0.299 มันแสดง. 3 ใน WPF UI ดังนั้นคำแนะนำของฉันให้ใช้รูปแบบสตริงต่อไปนี้

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

สวัสดีวิธีแก้ปัญหาของคุณโอเค แต่ฉันอยากใช้คีย์เวิร์ด N1 (2,3 ... ) เพราะหลีกเลี่ยงการพิมพ์ผิดและอย่างน้อยคุณก็มั่นใจว่าจะแสดงผลอย่างไร แต่คำแนะนำที่สองไม่ได้แสดงค่า 0 if <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.