【问题标题】:Trouble binding a floating point input field in WPF在 WPF 中绑定浮点输入字段时遇到问题
【发布时间】:2016-04-23 22:51:33
【问题描述】:

我最近开始使用 MVVM,偶然发现了一个似乎很多人都遇到过的问题。

基本上我的模型中有一个 double 类型的属性,它链接到我的 ViewModel 中的字符串属性,实现 INotifyPropertyChanged 接口,该接口绑定到文本框的 Text 属性,由此 UpdateSourceTrigger 设置为 PropertyChanged,但是,文本框不允许我输入小数位或减号,我也不能将文本框设置为空白而不会导致应用程序崩溃。

我彻底搜索了这个问题的解决方案,并找到了许多可能的解决方案,这些解决方案在某些方面有效,但给我留下了其他问题。最后,我使用了多种方法来解决这个问题:

我发现this 很有用,并通过放置:

public App()
{
    System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
}

在 App.xaml.cs 中,我现在可以在我的文本框中插入小数位。但是我仍然不能使用“-”,也不能将文本框设置为空白。

为了解决这个问题,我做了两件事。在我的 XAML 中,我将以下 StringFormat 添加到我的数据绑定中。

<TextBox Text="{Binding StringLinkedToDouble, UpdateSourceTrigger=PropertyChanged, StringFormat=-N2}"/>

“N2”之前的“-”允许我输入减号,但除非我先输入数值,然后在数字开头输入“-”,否则代码会出错。为了解决这个问题,以及我无法将文本框设置为空白而不遇到错误这一事实,我在 ViewModel 中执行了此操作:

public StringLinkedToDouble
{
    get { return _model.DoubleToBeLinked.ToString(); }
    set
    {
        if ((value != "") && (value != "-"))
        _model.DoubleToBeLinked = Convert.ToDouble(value);
        RaisePropertyChanged("StringLinkedToDouble");
    }
}

虽然这可能有效,但我是 MVVM 的新手,我发布这个的原因是因为这个解决方案看起来非常简单,几乎太简单了,我担心这可能不是 MVVM 的“好”?我有一半希望被告知这不公平哈!如果是这种情况,那么有人可以提出更好的选择吗?提前致谢! 另外,如果我做的其他事情不是正确的 MVVM,请告诉我:)

【问题讨论】:

  • 将文本框绑定到视图模型上的字符串应该很简单。我认为您在“我的模型中的..double 与字符串属性相关联..”方面做错了什么

标签: c# wpf xaml mvvm


【解决方案1】:

我不会说您的解决方案“太简单”。你自愿做了很多框架想要为你做的工作。

我会这样做:

查看模型

public class ViewModel : INotifyPropertyChanged
{
    private double _doubleValue = 0;
    public double DoubleValue
    {
        get { return _doubleValue; }
        set
        {
            _doubleValue = value;
            PropertyChanged?.Invoke(this, 
                new PropertyChangedEventArgs(nameof(DoubleValue)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

XAML

<Window 
    x:Class="WPFTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WPFTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>

    <Grid>
        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal" Margin="2">
                <Label>Double Value</Label>
                <TextBox 
                    Text="{Binding DoubleValue, UpdateSourceTrigger=PropertyChanged}" 
                    Width="300" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="2">
                <Label>Double Value</Label>
                <TextBox Text="{Binding DoubleValue}" Width="300" />
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

还有截图:

顶部的文本框有焦点。我输入了“-34”,“-34”通过视图模型绑定出现在第二个文本框中。然后我输入了垃圾,第一个文本框无法将字符串转换为双精度,所以默认验证显示红色错误边框——并且视图模型上的属性没有更新,因此第二个文本框没有更新.用户可以看到有问题。

如果您在这里的唯一目标只是让用户为您提供双倍的价值,那么以上就是您所需要的。

如果您想添加更多 UI 以帮助用户了解正在发生的事情,you can write a style or template trigger on Validation.HasError

我不喜欢拒绝接受非数字按键的数字字段,因为要使其正常工作非常困难——正如您在使用减号时所看到的那样。我对此并不虔诚,但我更愿意向他们显示错误并让他们决定他们想要输入哪些字符以及何时输入。

此外,从概念上讲,您的视图模型不应该知道这种验证。视图模型担心双重超出范围是有道理的,而不是担心用户输入的内容。视图模型应该有一个双重属性,并且有人在那里设置它,就是这样。检查最终用户键入的字符是视图的工作,而不是视图模型。把它留给TextBox(真的,它可能是Binding 做这项工作;出于某种原因,我从来没有费心去发现)让它保持在它所属的视图中。

您可能会尝试弄乱a custom value converter on the binding,但我认为没有任何方法可以让您尝试做所有事情。但我更喜欢像微软发布的那样使用 WPF 双重转换。我通常对他们发明那个轮子的方式感到满意。一个例外:尝试输入“-34e10”,当您输入“1”时,它会尝试“帮助”。但这可以通过将UpdateSourceTrigger 保留为默认值来解决,对于TextBox.Text,默认值是LostFocusthat default 是在DependencyProperty 在声明类上注册时确定的)。

【讨论】:

  • 我不得不承认我实际上并不知道您可以将双精度绑定到文本框的 Text 属性,因此我使用字符串哈哈!正是我想要的,非常感谢!
  • @Howard_Schmidtt NP! WPF 学习曲线的很大一部分是了解它可以自己弄清楚多少(以及知道它突然无法弄清楚的地方)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 2018-10-13
  • 1970-01-01
  • 2020-08-28
  • 2012-09-02
  • 2012-04-15
相关资源
最近更新 更多