2013-03-15 53 views
0

我很难理解我在做什么错误。基本上我试图在窗体上实现“取消”功能。当DataContext停留在同一个对象上时,MVVMLight工具包RaisePropertyChanged似乎没有更新UI

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

现在我有一个具有以下属性视图模型:

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

该视图更新了来自我的模型的所有数据。

我可以更改视图然后将其转移到我的模型没有问题

现在CancelCommand

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停留在同一个对象上,但它的属性发生变化,则视图。有没有办法强制更新而不使用这个临时变量?

在此先感谢。

回答

1

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

的一个方法是在你的资料库您CancelChanges方法来创建一个新的实例DairyProduct并返回,而不是操纵_currentDairyProduct的。然后CurrentDairyProduct将检测到新值并触发INPC。

更好的选择可能是通过CurrentDairyProduct而不是_currentDairyProduct。对CurrentDairyProduct的更改会触发INPC。

我相信,如果你制作一个变量私人它没有业务操纵超出其范围。我的意思是这就是为什么你有公共版本的权利?

+0

我曾尝试将公共和私有变量传递给相同结果的两个版本。我认为INPC不会对我的实体进行更改,因为它没有实际的触发器。如果我回到那个项目,我会尝试新的实例部分。谢谢。 – 2013-03-20 16:10:44