开发者

Auto cancel changes in DataForm when selection is changed

I wonder how you do such thing. Assume, we have MVVM CRUD app which modifies a tree (menu structure, for example). We have a view model with the menu items and two views: the first with a TreeV开发者_开发知识库iew and the second with a DataForm. Main problems are:

  1. DataForm can not handle hierarchical data.
  2. Depending on the menu item selected in the TreeView the DataForm should display different set of fields (for example for menu items with children or without).

I've ended up with the following. View model has 3 fields:

  1. Items — the collection of MenuItem objects which have their own Children collection for building hierarchical data source.
  2. SelectedItem — currently selected MenuItem in the TreeView.
  3. EditedItemEditViewModel object which basically has two descendants: MenuItemEditViewModel and LeafMenuItemEditViewModel. This property is set automatically when SelectedItem is changed. Its actual type is inferred from the SelectedItem.Children emptiness.

TreeView is bound to Items and SelectedItem. DataForm is not required to maintain currency in this case (instead current item is set by the TreeView) nor it is responsible for creating and deleting items. That's why I decided to bind only its CurrentItem to view model's EditedItem (ItemsSource is unbound). Its AutoCommit is set to False (when it is True and ItemsSource is unbound all current item changes get copied to newly selected item when you select different item in the TreeView, which is not so nice). DataForm fields are autogenerated.

Obviously, that now if we select an item in the TreeView, then make some changes in the DataForm and try to select different item in the TreeView we'll get well-known

Cannot change currency when an item has validation errors or it is being edited and AutoCommit is false. Set ItemsSource to a ICollectionView to manage currency instead

In this case I want DataForm to discard all changes implicitly. There is a workaround to call DataForm.CancelEdit() before TreeView selected item is changed (usually an event like PreviewSelectionChanged or BeforeSelectionChanged). But it is not the MVVM way since the TreeView and the DataForm are defined in completely different views (read: is not acceptable).

Is there something like AutoCancel which forces DataForm to cancel changes when its CurrentItem is changed? Maybe someone from dev team can answer? Or how would you deal with such problem?


I was surprised to find the Silverlight is severly lacking in this functionality, considering all the business oriented RIA functionality. AutoCommit is not acceptable to me because I want the user to explicitly acknowledge pending changes, rather than just commit something to the database that they may not want.

You can reliably track the edit mode of the DataForm using a private member variable and trapping the BeginningEdit and EditEnded events of the DataForm (naming inconsistency! Why one is called xxxEdit and the others are Editxxx is beyond me. Should it not be EditBeginning and EditEnded??). Inside the event handler for BeginningEdit, set the flag to true and set it to false in EditEnded.

In your SelectionChanged event, you can then check the flag. If it is true, you can call the CancelEdit on the DataForm.

private bool _editing = false;

public MainPage() {
    DataForm1.BeinningEdit += 
        new EventHandler<CancelEventArgs>(DataForm1_BeginningEdit);
    DataForm1.EditEnded += 
        new EventHandler<DataFormEditEndedEventArgs>(DataForm1_EditEnded);
}

protected void DataForm1_BeginningEdit(object sender, 
    System.ComponentModel.CancelEventArgs e) {
    _editing = true;
}

protected void DataForm1_EditEnded(object sender, 
    DataFormEditEndedEventArgs e) {
    _editing = false;
}

void TreeView1_SelectedItemChanged(object sender, 
    RoutedPropertyChangedEventArgs<object> e)
{
    if (_editing) {
        object previous = DataForm1.SelectedItem;
        object current = TreeView1.SelectedItem;

        if (MessageBox.Show("Are you sure you want to cancel the changes?", 
            "Confirm", MessageBoxbutton.OKCancel) == MessageBoxResult.OK) {
            DataForm1.CancelEdit();
        }
        else {
            TreeView1.SelectedItem = previous;
        }
    }
}


Have you tried to set AutoCommit at True ?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜