2013-05-21 25 views
0

我有一個XAML文件,其中包含一堆TextBlocks,以及一個包含這些值的平均值的標記的按鈕。按鈕的代碼是這樣的:將XAML C#標記加倍

<Button x:Name="ltavg_button" Cursor="Hand" Grid.Row="1" Grid.Column="3" FontSize="20" 
      Width="230" 
      Content="&lt; Average Systolic" 
      Tag="116.21428571428571" 
      Click="ltavg_button_Click"/> 

的代碼應該改變的TextBlock格雷的前景,要做到這一點需要從按鈕的標籤爲的TextBlocks的值,然後值(在列表中),然後將它們相互比較。問題在於標籤正在轉換爲一些無意義的奇怪值。

監聽器的代碼,在C#:

private void gtavg_button_Click(object sender, RoutedEventArgs e) 
{ 
    Double avg = Double.Parse(ltavg_button.Tag.ToString()); 
    foreach (TextBlock tb in dia) 
    { 
    int txt = int.Parse(tb.Text); 
    if (txt < avg) 
    { 
     tb.Foreground = new SolidColorBrush(DarkSlateGray); 
    } 
    } 
} 

因爲平均價值是如此怪異,它認爲該條件爲真,即使它不應該。一些值是110或更少,其他值高於120

任何幫助非常感謝,我一直在這個很長一段時間拉我的頭髮。

+0

嘗試'雙txt = double.Parse(tb.Text);' –

回答

0

您想告訴Parse()方法您使用哪種文化來表示double值的文本。在這種情況下,應該是十進制符號,但在其他文化中,它被用作千位分隔符。你的解析方法調用改成這樣:

Double avg = Double.Parse(ltavg_button.Tag.ToString(), CultureInfo.InvariantCulture); 

,並確保

using System.Globalization; 

頂部添加到您使用的語句。這將告訴Parse方法它應該使用不變的文化來解析Tag值,這就是你想要的。

這也可以解釋爲什麼你的比較總是返回true:你可能沒有比較110或120與116.21428571428571,而是比較11621428571428571.0。

當使用ToString()調用Parse()或將數字轉換爲字符串時,始終提供一個IFormatProvider。否則,你永遠不知道如果你的代碼在具有不同文化設置的機器上運行會發生什麼。

+0

-1。這鼓勵使用非常不好的做法。看到我的答案。 –

+0

我意識到不好的做法,但我認爲如果OP在解析/轉換數字數字時遇到文化的重要性等問題,那麼告訴他/她改變應用程序的整個架構將會是超越他們當前的專業水平。 – Bas

1

好的。刪除所有的代碼並從頭開始。

首先,您有一個嚴重的誤解:The UI is NOT the right place to store data

所以,你不應該被放置你的數值在XAML,而是應該創建一個適當的視圖模型來存儲這些數據,並對其進行操作:

<Window x:Class="MiscSamples.AverageNumbersSample" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="AverageNumbersSample" Height="300" Width="300"> 
    <DockPanel> 
     <Button Content="Calculate" Click="Calculate" DockPanel.Dock="Top"/> 
     <ListBox ItemsSource="{Binding}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Value}" x:Name="txt"/> 
        <DataTemplate.Triggers> 
         <DataTrigger Binding="{Binding IsBelowAverage}" Value="True"> 
          <Setter TargetName="txt" Property="Foreground" Value="Blue"/> 
         </DataTrigger> 
        </DataTemplate.Triggers> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </DockPanel> 
</Window> 

代碼背後:

public partial class AverageNumbersSample : Window 
{ 
    public double Average = 116.21428571428571; 
    public List<AverageSampleViewModel> Values { get; set; } 

    public AverageNumbersSample() 
    { 
     InitializeComponent(); 
     DataContext = Values = Enumerable.Range(100, 150) 
             .Select(x => new AverageSampleViewModel() { Value = x }) 
             .ToList(); 
    } 

    private void Calculate(object sender, RoutedEventArgs e) 
    { 
     Values.ForEach(x => x.IsBelowAverage = x.Value < Average); 
    } 
} 

數據項:

public class AverageSampleViewModel: PropertyChangedBase 
{ 
    public int Value { get; set; } 

    private bool _isBelowAverage; 
    public bool IsBelowAverage 
    { 
     get { return _isBelowAverage; } 
     set 
     { 
      _isBelowAverage = value; 
      OnPropertyChanged("IsBelowAverage"); 
     } 
    } 
} 

PropertyChangedBase類(MVVM助手)

public class PropertyChangedBase:INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     Application.Current.Dispatcher.BeginInvoke((Action) (() => 
                   { 
                    PropertyChangedEventHandler handler = PropertyChanged; 
                    if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
                   })); 
    } 
} 

結果:

enter image description here

  • 在這個意義上說,WPF是從別的根本不同的目前存在(如可用於Java或類似的東西多恐龍古老的UI框架)。
  • 您一定不要使用UI來store數據,而應使用UI來show數據。這些概念是根本不同的。
  • 我的例子(這是做WPF應用程序的正確方法),不需要int.Parse()或類似的東西,因爲ViewModel已經有了所需的正確的數據類型。