【问题标题】:IValueConverter and Metric/Imperial unitsIValueConverter 和公制/英制单位
【发布时间】:2017-02-10 13:57:25
【问题描述】:

我计划实现代码,该代码将使用 IValueConverter 根据用户设置的布尔值以公制或英制显示度量单位。我面临的问题是存储在我的数据库中的数据必须始终采用公制。如果有区别,我会先使用实体​​框架数据库。

所以我想知道的情况是:如果用户选择以英制单位显示数据,但随后更改了其中一个字段并将其保存 - 我如何确保它以公制正确保存?从我通过在线研究收集的信息来看,这似乎是转换器的 ConvertBack 方法的一部分?现在我调用 Textbox.GetBindingExpression(TextBox.TextProperty).UpdateSource();保存数据,我不明白如何使它工作,因为据我所知,它只是抓取 TextBox 中的值并保存它。我是对的,或者如果有一个 ConvertBack 方法会被调用以获取 TextProperty?

另外,一般来说,我是否以正确的方式进行此操作(即使用 IValueConverter 来更改显示)?老实说,我在这个项目上有点不知所措,但我的最后期限很快就要到了,我迫切需要把这件事做好。任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • 您需要将您的文本框与 Mode=TwoWay 绑定。然后,当您的模型设置文本框中的值时,将调用您的转换器 ConvertBack。
  • 好的@Evk。就这样我确定我明白了:如果我设置 Mode=TwoWay 那么当我调用 Textbox.GetBindingExpression(TextBox.TextProperty).UpdateSource();那么它应该保存 ConvertBack() 转换器的结果吗?抱歉,如果我听起来很密集,我只是想确定一下。感谢您的帮助。
  • 感谢@Rom 的链接
  • 您根本不需要调用 UpdateSource。使用 TwoWay 绑定,当您更改 TextBox 中的文本时(失去焦点或立即查看链接问题) - 它会更新模型中的值(通过转换器的 ConvertBack 方法,如果有转换器)。

标签: c# wpf entity-framework units-of-measurement


【解决方案1】:

所以您有一些模型,并且您想使用TextBoxValueConverter 编辑该模型的一些属性。让我们使用一些虚拟值转换器,它将值乘以 10,然后在ConvertBack 中将值除以 10

public class MyConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value == null || value == DependencyProperty.UnsetValue)
            return null;
        return (decimal) value*10;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value == null || value == DependencyProperty.UnsetValue)
            return 0;
        decimal d;
        if (decimal.TryParse((string) value, out d))
            return d/10;
        return 0;
    }
}

现在是一些测试模型

public class MyModel : INotifyPropertyChanged {
    private decimal _someValue;

    public decimal SomeValue
    {
        get { return _someValue; }
        set
        {
            if (value == _someValue) return;
            _someValue = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

然后你就有了你的文本框

<TextBox Width="150" Height="20" Text="{Binding SomeValue, Mode=TwoWay, Converter={StaticResource myConverter}, UpdateSourceTrigger=PropertyChanged}" />

如果您使用UpdateSourceTrigger=PropertyChanged,则在每次用户编辑时,该值将传递给您的 ConvertBack 方法,并将结果分配给您模型的 SomeValue。

当用户按下保存按钮时,您只需使用您拥有的任何方法将模型保存到数据库。您不需要显式更新模型的属性,因为它们已经是最新的。您也可以使用UpdateSourceTrigger=LostFocus(默认一个)。然后,每当字段失去焦点时 - 模型中的属性将与之同步(再次通过ConvertBack

【讨论】:

  • 好的。我想我现在明白了。出于某种原因,我认为调用 UpdateSource() 是在将实际保存到我的数据库中。我仔细看了看,当我调用 DTE.ChangeTracker.DetectChanges(); 时,这实际上发生了。 DTE.SaveChanges(); DTE 是我的数据库上下文。我现在明白了。凉爽的。唯一阻止我实现你放在那里的东西是我的模型没有实现 INotifyPropertyChanged 因为我首先使用了数据库。可能只需要硬着头皮使用 CodeFirst。无论哪种方式,你已经给了我足够的指引我正确的方向。
  • 非常非常非常感谢@Evk。非常感谢您抽出时间与我详细讨论此问题。你真棒。我将您的答案标记为已接受。我希望你有一个美好的一天。
猜你喜欢
  • 2020-01-30
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-24
  • 2019-03-20
  • 2011-10-24
  • 1970-01-01
相关资源
最近更新 更多