2013-08-21 88 views
61

Tôi đang viết một chương trình WPF và tôi đang cố gắng tìm ra cách để định dạng dữ liệu trong một TextBox thông qua một số phương pháp lặp lại như một kiểu hoặc mẫu. Tôi có rất nhiều TextBoxes (95 là chính xác) và mỗi TextBox được gắn với dữ liệu số riêng của nó mà mỗi cái có độ phân giải riêng được xác định. Ví dụ, nếu dữ liệu là 99.123 với độ phân giải là 2 thì nó sẽ hiển thị 99.12. Tương tự, giá trị dữ liệu là 99 và độ phân giải 3 sẽ được hiển thị là 99.000 (không phải 99). Có cách nào để làm việc này không?Làm cách nào để định dạng số vị trí thập phân trong wpf bằng cách sử dụng kiểu/mẫu?

Edit: Tôi nên làm rõ, có 95 textbox trên màn hình hiện tại tôi đang làm việc trên, nhưng tôi muốn mọi TextBox suốt các màn hình khác nhau trong chương trình của tôi để hiển thị chính xác số chữ số thập phân. Bây giờ tôi nghĩ về nó, một số trong số này là TextBoxes (giống như màn hình tôi đang làm bây giờ) và một số là DataGrids hoặc ListViews, nhưng nếu tôi có thể tìm ra cách làm cho nó hoạt động cho TextBoxes. nó ra cho các điều khiển khác là tốt.

Không có nhiều mã để chia sẻ trong trường hợp này nhưng tôi sẽ cố gắng để làm cho nó rõ ràng hơn:

Tôi có một Xem mẫu, trong đó có các thuộc tính sau (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 

và trong XAML tôi có:

<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 (giải pháp của tôi): Nó chỉ ra rằng sau khi bỏ đi fr om máy tính một lúc, tôi quay lại tìm một câu trả lời đơn giản đang nhìn chằm chằm vào mặt tôi. Định dạng dữ liệu trong mô hình xem!

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

sử dụng 'IValueConverter'? Vượt qua giá trị thực tế và độ phân giải cho bộ chuyển đổi và để cho nó làm tròn cho bạn bên trong chính nó. Thật khó để đề xuất một 'StringFormat' mà không biết chính xác 95 'TextBox' này được tạo ra như thế nào. – Viv

+0

Đăng mã hiện tại và XAML. Nếu không thì đó là tất cả những suy đoán và sự đoán mò vô ích. –

+0

Tôi đã thêm một số thông tin khác vào câu hỏi mà hy vọng sẽ làm cho nó rõ ràng hơn. – AXG1010

Trả lời

124

Bạn nên sử dụng StringFormat trên Binding. Bạn có thể sử dụng một trong hai standard string formats, hoặc custom string formats:

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

Lưu ý rằng StringFormat chỉ hoạt động khi thuộc tính mục tiêu là kiểu string. Nếu bạn đang cố gắng thiết lập một cái gì đó như một tài sản Content (typeof(object)), bạn sẽ cần phải sử dụng tùy chỉnh StringFormatConverter (like here) và chuyển chuỗi định dạng của bạn làm ConverterParameter.

Chỉnh sửa cho câu hỏi được cập nhật

Vì vậy, nếu ViewModel bạn xác định chính xác, tôi khuyên bạn nên làm điều này như một MultiBinding, và tạo riêng IMultiValueConverter của bạn. Điều này là khá khó chịu trong thực tế, để đi từ một ràng buộc đơn giản với một trong đó cần phải được mở rộng ra một MultiBinding, nhưng nếu độ chính xác không được biết tại thời gian biên dịch, điều này là khá nhiều tất cả các bạn có thể làm. IMultiValueConverter của bạn sẽ cần lấy giá trị, độ chính xác và xuất chuỗi đã định dạng. Bạn có thể thực hiện việc này bằng cách sử dụng String.Format.

Tuy nhiên, đối với những thứ như một ContentControl, bạn có thể dễ dàng hơn nhiều làm điều này với một Style:

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

Bất kỳ sự kiểm soát đó cho thấy nhiều một ContentStringFormat thể được sử dụng như thế này. Thật không may, TextBox không có bất cứ điều gì như thế.

+0

Cảm ơn thông tin Abe. – AXG1010

+1

Ví dụ với StringFormat được đặt thành '#, #. 00' không biên dịch - dấu phẩy được hiểu là dấu phân tách cho các thuộc tính trong phần mở rộng đánh dấu' Binding'. – Gigi

+0

@Gigi, bạn nói đúng, nhưng bạn có thể dễ dàng sử dụng nó như vậy: 'StringFormat = {} {0: #, #. 00}'. Tôi sẽ cập nhật câu trả lời để hoạt động chính xác. –

0
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; 
     } 
    } 
+4

Một số giải thích sẽ cải thiện đáng kể chất lượng câu trả lời của bạn. – mrun

1

Câu trả lời được chấp nhận không hiển thị 0 ở vị trí nguyên cho đầu vào như 0,299. Nó hiển thị .3 trong giao diện người dùng WPF. Vì vậy, đề xuất của tôi để sử dụng định dạng chuỗi sau

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