2

标题或多或少总结了它。如果我们有一个完全干净的 WPF 应用程序,并添加以下 ViewModel:

using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication10
{
    public sealed class ViewModel
    {
        private readonly ObservableCollection<MyObject> _myObjects = new ObservableCollection<MyObject>();

        public ViewModel()
        {
            for (var i = 0; i < 5; i++)
            {
                _myObjects.Add(new MyObject(i, i));
            }
        }

        public ObservableCollection<MyObject> MyObjects
        {
            get { return _myObjects; }
        }
    }

    public sealed class MyObject : INotifyPropertyChanged
    {
        private double _unitStake;
        private decimal _unitStakeDecimal;

        public decimal UnitStakeDecimal
        {
            get { return _unitStakeDecimal; }
            set
            {
                if (value == _unitStakeDecimal) return;
                _unitStakeDecimal = value;
                OnPropertyChanged("UnitStakeDecimal");
            }
        }

        public MyObject(double unitStake, decimal unitStakeDecimal)
        {
            UnitStake = unitStake;
            UnitStakeDecimal = unitStakeDecimal;
        }

        public double UnitStake
        {
            get { return _unitStake; }
            set
            {
                if (value.Equals(_unitStake)) return;
                _unitStake = value;
                OnPropertyChanged("UnitStake");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

然后将以下 XAML 添加到 MainWindow:

<Window x:Class="WpfApplication10.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" DataContext="{StaticResource ViewModel}">
    <Grid>

        <DataGrid CanUserAddRows="False" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding MyObjects}"  RowDetailsVisibilityMode="VisibleWhenSelected" Grid.Row="1">
            <DataGrid.Columns>
                    <DataGridTextColumn Header="Unit Stake" 
                                        Binding="{Binding UnitStake,UpdateSourceTrigger=PropertyChanged}" 
                                        Width="Auto" />

                <DataGridTextColumn Header="Unit Stake Dec" 
                                        Binding="{Binding UnitStakeDecimal,UpdateSourceTrigger=PropertyChanged}" 
                                        Width="Auto" />
            </DataGrid.Columns>
        </DataGrid>

    </Grid>
</Window>

我们有一个超级简单的 MVVM 应用程序,在 DataGrid 中包含一个 DataGridTextColumn。此 DataGridTextColumn 中的一列绑定到 double 属性,另一列绑定到 decimal 属性。

当我们运行它并尝试修改Unit Stake列中的值时,假设我们想要将其更改为 0.05,因此准确键入它,它会更改为 5。

这不会发生在 Unit Stake Dec 列(绑定到小数)。这导致了一些重大问题,那么我该如何解决这个问题,以便当用户键入.05时, double 属性的值实际上是.05而不是5

如果我将绑定到 double 属性的 DataGridTextColumn 列的 UpdateSourceTrigger 属性设置为 LostFocus,那么事情会按预期工作,但是这里可能会丢失数据,以及为什么我不必对绑定到的列执行此操作小数属性?

谢谢

4

1 回答 1

0

您是否对下面的代码行有任何想法

if (value.Equals(_unitStake)) return;

查看何时在 ViewModel 类中创建 MyObject 实例

for (var i = 0; i < 5; i++)
{
    _myObjects.Add(new MyObject(i, i));
}

所以它们基本上是用整数类型初始化的,当你这样做时

value.Equals(_unitStake)

它将始终返回 false,因为这两种类型不相等。因此,您无法设置属性 StakeUnit。在 UnitStakeDecimal 的情况下,您比较它们的值

if (value == _unitStakeDecimal) return;

哪个有效并返回准确的结果,以便您能够设置属性。

于 2013-07-23T04:23:59.293 回答