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

ビューは、モデルのすべてのデータで更新されます。

ビューに変更を加えて、問題なくモデルに転送することができます

ここで、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が同じオブジェクトにとどまっているが、プロパティが変更された場合に、ビューを更新するために何をすべきかということです。この一時変数を使用せずに強制的に更新する方法はありますか?

前もって感謝します。

4

1 に答える 1

1

CurrentDairyProductを独自のバッキングフィールドで更新しようとしているようです。_currentDairyProductをリポジトリメソッドに渡し、直接操作してから返すと思います。そうすることで、INPCをトリガーしないため、ビューが更新されなくなります。CurrentDairyProductに割り当て直そうとすると、値が同じになるため、INPCもトリガーされません。nullに設定し、CurrentDairyProductを再割り当てすると、変更が検出されるため、INPCがトリガーされます。

これを修正する1つの方法は、リポジトリのCancelChangesメソッドに新しいインスタンスDairyProductを作成し、_currentDairyProductを操作する代わりにそれを返すことです。次に、CurrentDairyProductは新しい値を検出し、INPCをトリガーします。

より良い代替策は、_currentDairyProductの代わりにCurrentDairyProductを渡すことです。CurrentDairyProductを変更すると、INPCがトリガーされます。

変数をプライベートにすると、その範囲外で操作されるビジネスはないと思います。だからあなたは公開版を持っているのですか?

于 2013-03-16T10:30:22.947 に答える