【问题标题】:XAML C# Tag to DoubleXAML C# 标记加倍
【发布时间】:2013-05-21 14:33:06
【问题描述】:

我有一个 XAML 文件,其中包含一堆 TextBlock,还有一个带有标签的按钮,其中包含这些值的平均值。按钮的代码是这样的:

<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 的前景更改为灰色,为此它从按钮的标记中获取值,然后获取文本块(在列表中)的值,然后将它们与它们进行比较彼此。问题是标签被转换为一些没有任何意义的奇怪值。

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

因为 avg 值太奇怪了,它认为条件为真,即使它不应该是。有些值小于等于 110,有些值大于 120

非常感谢任何帮助,我已经为此烦恼了很长时间。

【问题讨论】:

  • 试试double txt = double.Parse(tb.Text);

标签: c# xaml tags double


【解决方案1】:

好的。删除所有代码并重新开始。

首先,您在这里有一个严重的误解:The UI is NOT the right place to store data

因此,您不应该将数值放在 XAML 中,而是应该创建一个适当的 ViewModel 来存储这些数字并对其进行操作:

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

结果:

  • 从这个意义上说,WPF 与当前存在的任何其他东西(例如可用于 java 或类似的东西的多个恐龙古老 UI 框架)根本不同。
  • 您绝不能使用 UI 来处理 store 数据,而是使用 UI 来处理 show 数据。这些概念根本不同。
  • 我的示例(这是执行 WPF 应用程序的正确方法)不需要 int.Parse() 或任何类似的转换内容,因为 ViewModel 已经具有所需的正确数据类型。

【讨论】:

    【解决方案2】:

    您想告诉 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。否则你永远不知道如果你的代码在具有不同文化设置的机器上运行会发生什么。

    【讨论】:

    • -1。这鼓励使用非常糟糕的做法。看我的回答。
    • 我意识到了不好的做法,但我认为如果 OP 在解析/转换数字时遇到文化重要性等基本问题,告诉他/她改变整个架构的应用程序将超出他们目前的专业水平。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多