0

我很难理解我做错了什么。基本上我正在尝试在表单上实现“取消”功能。

我有一个模型,它实现了工具包的 ObservableObject 并映射到一个 EF 实体类。当我调用我的 CancelChanges() 方法时,它基本上使用 StoreWins 执行 context.Refresh()。

现在我有一个具有以下属性的 ViewModel:

    /// <summary>
    /// The <see cref="CurrentDairyProduct" /> property's name.
    /// </summary>
    public const string CurrentDairyProductPropertyName = "CurrentDairyProduct";

    private DairyProduct _currentDairyProduct = null;

    /// <summary>
    /// Sets and gets the CurrentDairyProduct property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public DairyProduct CurrentDairyProduct
    {
        get
        {
            return _currentDairyProduct;
        }

        set
        {
            RaisePropertyChanging(CurrentDairyProductPropertyName);
            _currentDairyProduct = value;
            RaisePropertyChanged(CurrentDairyProductPropertyName);
        }
    }

和这种形式的视图

<Grid HorizontalAlignment="Left" Margin="27,14,0,0" Name="grid1" VerticalAlignment="Top"  DataContext="{Binding Path=CurrentDairyProduct, Mode=OneWay, NotifyOnSourceUpdated=True}">

        <Grid.Resources>
            <Style TargetType="{x:Type TextBox}">
                <Style.Triggers>
                    <Trigger Property="Validation.HasError" Value="true">
                        <Setter Property="ToolTip" 
Value="{Binding RelativeSource={RelativeSource Self},
  Path=(Validation.Errors)[0].ErrorContent}"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
        <Label Content="DAIRY PRODUCT CODE:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
        <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Text="{Binding Path=DairyProductCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" VerticalAlignment="Center" Width="120" />
        <Label Content="DAIRY PRODUCT NAME EN:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
        <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Text="{Binding Path=DairyProductNameEn, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" VerticalAlignment="Center" Width="120" />
        <Label Content="DAIRY PRODUCT NAME FR:" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
        <TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="3" Text="{Binding Path=DairyProductNameFr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" VerticalAlignment="Center" Width="120" />

    </Grid>
    <Button Content="Save" Height="29" HorizontalAlignment="Left" Margin="342,332,0,0" Name="button1" 
              VerticalAlignment="Top" Width="87" Command="{Binding Path=SaveCommand}" />
    <Button Content="Cancel" Height="29" HorizontalAlignment="Left" Margin="442,332,0,0" Name="button2" 
              VerticalAlignment="Top" Width="87" Command="{Binding Path=CancelCommand}" />

当我调用以下语句从数据库中获取数据时,一切正常

CurrentDairyProduct = _dairyProductRepository.GetObservableObjectById(_currentDairyProductId);

视图会使用我的模型中的所有数据进行更新。

我可以对视图进行更改,然后毫无问题地转移到我的模型中

现在取消命令

protected override void CancelChanges()
{
    CurrentDairyProduct = _dairyProductRepository.CancelChanges(_currentDairyProduct);

}

这在理论上应该调用 CurrentDairyProduct 的设置器,而后者又调用 RaisePropertyChanged。这有效,因为我可以调试它。不幸的是,视图根本没有更新。

出于好奇,我将 CancelCommand 代码更改为以下内容:

protected override void CancelChanges()
{
    //CurrentDairyProduct = _dairyProductRepository.CancelChanges(_currentDairyProduct);
    DairyProduct temp = _dairyProductRepository.CancelChanges(_currentDairyProduct);
    CurrentDairyProduct = null;
    CurrentDairyProduct = temp;
 }

使用此代码,视图确实会更新...

我的问题是,如果实际的 DataContext 保持在同一个对象上但它的属性发生变化,我应该怎么做才能更新视图。有没有办法在不使用这个临时变量的情况下强制更新?

提前致谢。

4

1 回答 1

1

您似乎正在尝试使用自己的支持字段更新 CurrentDairyProduct 。我猜您将 _currentDairyProduct 传递给您的存储库方法并直接操作它,然后返回它。通过这样做,您不会触发 INPC,因此不会发生视图更新。当您尝试将其分配回 CurrentDairyProduct 时,该值现在是相同的,因此 INPC 也不会触发。当您将其设置为 null 并重新分配 CurrentDairyProduct 时,会检测到更改并因此触发 INPC。

解决此问题的一种方法是在存储库的 CancelChanges 方法中创建一个新实例 DairyProduct 并返回它,而不是操作 _currentDairyProduct。CurrentDairyProduct 然后将检测到一个新值并触发 INPC。

更好的选择可能是传递 CurrentDairyProduct 而不是 _currentDairyProduct。CurrentDairyProduct 的更改将触发 INPC。

我相信,如果您将变量设为私有,则不会在其范围之外进行操作。我的意思是这就是为什么你有一个公共版本对吧?

于 2013-03-16T10:30:22.947 回答