0

I have a XAML file with a bunch of TextBlocks in them, and a button with a tag which contains the average of those values. The code for the button is this:

<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"/>

The code is supposed to change the foreground of the TextBlock to Grey, and to do that it takes the value from the button's tag, and then value for the textblocks (which are in a list), and then compares to them to each other. The problem is that the tag is being converted to some weird value that doesn't make any sense.

The listener code, in 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);
     }
   }
 }

Because the avg value is so weird, it considers the condition true even if it shouldn't be. Some values are 110 or less, others are higher than 120

Any help is greatly appreciated, I've been pulling my hair out over this for a long time.

4

2 回答 2

1

Ok. Delete all your code and start all over.

First of all, you have a SERIOUS misconception here: The UI is NOT the right place to store data.

Therefore, you should NOT be placing your numeric values in XAML, but instead you should create a proper ViewModel to store these numbers and operate on them:

<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>

Code Behind:

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

Data Item:

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

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

PropertyChangedBase class (MVVM Helper)

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

Result:

enter image description here

  • In this sense, WPF is fundamentally different from anything else currently in existence (such as the multiple dinosaur archaic UI frameworks available for java or stuff like that).
  • You must NEVER use the UI to store data, instead you use the UI to show data. These concepts are fundamentally different.
  • My example (which is the RIGHT way to do WPF applications), removes the need for int.Parse() or any casting stuff like that, because the ViewModel already has the proper data type required.
于 2013-05-21T15:06:41.483 回答
0

您想告诉 Parse() 方法您使用哪种文化来表示双精度值的文本。在这种情况下,. 应该表示十进制符号,但在其他文化中它被用作千位分隔符。将您对 parse 方法的调用更改为:

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

并确保添加

using System.Globalization;

到顶部的 using 语句。这将告诉 Parse 方法它应该使用不变的文化来解析 Tag 值,这就是你想要的。

这也可以解释为什么您的比较始终返回 true:您可能不是将 110 或 120 与 116.21428571428571 进行比较,而是与 11621428571428571.0 进行比较。

调用 Parse() 或使用 ToString() 将数字转换为字符串时,始终提供 IFormatProvider。否则,如果您的代码在具有不同文化设置的机器上运行,您永远不知道会发生什么。

于 2013-05-21T14:49:28.193 回答