CancelViewModel not working in my scenario - trying to edit the node of a tree.

Topics: Questions
Jul 20, 2012 at 6:20 PM

Hi Geert,

I have seen this discussion, however I still can't get it to work in my scenario:
http://catel.codeplex.com/discussions/269280

I have a ReportViewModel and a ReportView.
The ReportView holds a tree that binds to   ObservableCollection<ObservableNode<ReportItem>>.
I would like to edit an item and if it fails while updating the database, I want to cancel the view model. Can you point me in the right direction? What other alternatives do I have to cancel the view model, in case I can't get this to work? Thank you.

 

Each node in the tree has an edit template. The edit template looks like this:


partial ReportView:

   <UserControl.Resources>
    <DataTemplate x:Key="NodeEditTemplate">
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <Views:ObservableNodeView/>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </UserControl.Resources>

 

ObservableNodeView:

<catel:UserControl x:Class="WPFCatelTelerik.Views.ObservableNodeView"
                   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
				   xmlns:catel="http://catel.codeplex.com"
                   xmlns:Converters="clr-namespace:WPFCatelTelerik.Converters"
                   xmlns:Models="clr-namespace:WPFCatelTelerik.Models">
  
   
        <!-- NodeText -->
        <Label Content="Text" />
        <TextBox DataContext="{Binding UserData}" 
                 Text="{Binding NodeText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True, NotifyOnValidationError=True}" 
                 TextWrapping="Wrap" 
                 Width="250" Height="100"
                 ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                 ScrollViewer.VerticalScrollBarVisibility="Auto" />
 
 
</catel:UserControl>

The event handlers that handle the edit are:

//--------------------------------------------------------------------------------
        // [event-handlers]
        //--------------------------------------------------------------------------------

       
        private void OnEnterEditModeExecute()
        {
            if (SelectedReportItem != null)
            {
                observableNodeViewModel = new ObservableNodeViewModel(SelectedReportItem);
                observableNodeViewModel.UserData.IsInEditMode = true;
            }
        }

        private void OnPreviewEditedExecute()
        {
            this.serviceAgent.UpdateReportItem(SelectedReportItem.UserData, (ri, ex) =>
            {
                if (ex != null)
                {
                    observableNodeViewModel.CancelViewModel();
                    // It fails to cancel here
                   // somehow it does not cancel UsereData changes

                }
            });
        }


Below is part of the code so it will be easier to follow:

ReportViewModel:

public class ReportViewModel : ViewModelBase
    {  

        //--------------------------------------------------------------------------------
        // [fields]
        //--------------------------------------------------------------------------------

        private IReportServiceAgent serviceAgent;
        private ObservableNodeViewModel observableNodeViewModel;
        private ObservableNode<ReportItem> rootNode;


        //--------------------------------------------------------------------------------
        // [properties]
        //--------------------------------------------------------------------------------

        public override string Title { get { return "Report ViewModel title"; } }

        public ObservableCollection<ObservableNode<ReportItem>> ReportItems
        {
            get { return GetValue<ObservableCollection<ObservableNode<ReportItem>>>(ReportItemsProperty); }
            set { SetValue(ReportItemsProperty, value); }
        }
        public static readonly PropertyData ReportItemsProperty = RegisterProperty("ReportItems", typeof(ObservableCollection<ObservableNode<ReportItem>>));

        public ObservableNode<ReportItem> SelectedReportItem // if multiple selection enabled - it always holds the first selected item
        {
            get { return GetValue < ObservableNode<ReportItem>>(SelectedReportItemProperty); }
            set { SetValue(SelectedReportItemProperty, value); }
        }
        public static readonly PropertyData SelectedReportItemProperty = RegisterProperty("SelectedReportItem", typeof(ObservableNode<ReportItem>));

        public ObservableNode<ReportItem>[] SelectedReportItems
        {
            get
            {
                return GetSelectedReportItems();
            }
        }

        public Command EnterEditMode { get; private set; }
        public Command PreviewEdited { get; private set; }


        //--------------------------------------------------------------------------------
        // [constructors]
        //--------------------------------------------------------------------------------

        public ReportViewModel()
            : base()
        {
            Initialize(null);
            LoadReportItems();           
        }

        public ReportViewModel(IReportServiceAgent serviceAgent)
        {     
            Initialize(serviceAgent);
            LoadReportItems();
        }


        //--------------------------------------------------------------------------------
        // [event-handlers]
        //--------------------------------------------------------------------------------

       
        private void OnEnterEditModeExecute()
        {
            if (SelectedReportItem != null)
            {
                observableNodeViewModel = new ObservableNodeViewModel(SelectedReportItem);
                observableNodeViewModel.UserData.IsInEditMode = true;
            }
        }

        private void OnPreviewEditedExecute()
        {
            this.serviceAgent.UpdateReportItem(SelectedReportItem.UserData, (ri, ex) =>
            {
                if (ex != null)
                {
                    observableNodeViewModel.CancelViewModel();
                }
            });
        }

       
        //--------------------------------------------------------------------------------
        // [methods]
        //--------------------------------------------------------------------------------

        private void Initialize(IReportServiceAgent agent)
        {
            if (agent == null)
                this.serviceAgent = ServiceLocator.ResolveType<IReportServiceAgent>();
            else
                this.serviceAgent = agent;

            ReportItems = new ObservableCollection<ObservableNode<ReportItem>>();
            this.rootNode = new ObservableNode<ReportItem>();

            EnterEditMode = new Command(OnEnterEditModeExecute);
            PreviewEdited = new Command(OnPreviewEditedExecute);
       }
    }





ObservableNode

public class ObservableNode<T> : IEditableObject // I have also tried public class ObservableNode<T> : DataObjectBase<T> where T: class - still not working
    {
        //--------------------------------------------------------------------------------
        // [properties]
        //--------------------------------------------------------------------------------

        public T UserData { get; set; }
        public ObservableNode<T> Parent { get; private set; }
        public ObservableCollection<ObservableNode<T>> Children { get; private set; }
        public NodeType NodeType { get; set; }


        //--------------------------------------------------------------------------------
        // [constructors]
        //--------------------------------------------------------------------------------

        public ObservableNode()
        {
            Parent = null;
            Children = new ObservableCollection<ObservableNode<T>>();
            NodeType = NodeType.Unknown;
        }

        public ObservableNode(T data)
        {
            UserData = data;
            Parent = null;
            Children = new ObservableCollection<ObservableNode<T>>();
            NodeType = NodeType.Unknown;
        }

        internal ObservableNode(ObservableNode<T> parent, T data)
        {
            UserData = data;
            Parent = parent;
            Children = new ObservableCollection<ObservableNode<T>>();
            NodeType = NodeType.Unknown;
        }


        //--------------------------------------------------------------------------------
        // [methods]
        //--------------------------------------------------------------------------------

        public void BeginEdit()
        {
           
        }

        public void CancelEdit()
        {
            // ((IEditableObject)this.UserData).CancelEdit();
        }

        public void EndEdit()
        {

        }
    }



ObservableNodeViewModel

public class ObservableNodeViewModel : ViewModelBase
    {
        //--------------------------------------------------------------------------------
        // [constructors]
        //--------------------------------------------------------------------------------

        public ObservableNodeViewModel(ObservableNode<ReportItem> observableNode)
        {
            ObservableNodeReportItem = observableNode ?? new ObservableNode<ReportItem>();
        }


        //--------------------------------------------------------------------------------
        // [properties]
        //--------------------------------------------------------------------------------

        public override string Title { get { return "ObservableNodeReportItem window title"; } }

        [Model]
        public ObservableNode<ReportItem> ObservableNodeReportItem
        {
            get { return GetValue<ObservableNode<ReportItem>>(ObservableNodeReportItemProperty); }
            private set { SetValue(ObservableNodeReportItemProperty, value); }
        }
        public static readonly PropertyData ObservableNodeReportItemProperty = RegisterProperty("ObservableNodeReportItem", typeof(ObservableNode<ReportItem>));

        [ViewModelToModel("ObservableNodeReportItem", "UserData")]
        public ReportItem UserData
        {
            get { return GetValue<ReportItem>(UserDataProperty); }
            set { SetValue(UserDataProperty, value); }
        }
        public static readonly PropertyData UserDataProperty = RegisterProperty("UserData", typeof(ReportItem));
    }


ReportItem

public class ReportItem : DataObjectBase<ReportItem>
    {
        //--------------------------------------------------------------------------------
        // [properties]
        //--------------------------------------------------------------------------------

        public int ReportNodeId
        {
            get { return GetValue<int>(ReportNodeIdProperty); }
            set { SetValue(ReportNodeIdProperty, value); }
        }
        public static readonly PropertyData ReportNodeIdProperty = RegisterProperty("ReportNodeId", typeof(int), default(int));

        public int ProjectId
        {
            get { return GetValue<int>(ProjectIdProperty); }
            set { SetValue(ProjectIdProperty, value); }
        }
        public static readonly PropertyData ProjectIdProperty = RegisterProperty("ProjectId", typeof(int), default(int));

        public List<Message> Messages
        {
            get { return GetValue<List<Message>>(MessagesProperty); }
            set { SetValue(MessagesProperty, value); }
        }
        public static readonly PropertyData MessagesProperty = RegisterProperty("Messages", typeof(List<Message>), null);

        public int ReportNodeTypeId
        {
            get { return GetValue<int>(ReportNodeTypeIdProperty); }
            set { SetValue(ReportNodeTypeIdProperty, value); }
        }
        public static readonly PropertyData ReportNodeTypeIdProperty = RegisterProperty("ReportNodeTypeId", typeof(int), default(int));

        public ReportNodeType ReportNodeType
        {
            get { return GetValue<ReportNodeType>(ReportNodeTypeProperty); }
            set { SetValue(ReportNodeTypeProperty, value); }
        }
        public static readonly PropertyData ReportNodeTypeProperty = RegisterProperty("ReportNodeType", typeof(ReportNodeType), ReportNodeType.Unknown);
       
        public int ParentReportNodeId
        {
            get { return GetValue<int>(ParentReportNodeIdProperty); }
            set { SetValue(ParentReportNodeIdProperty, value); }
        }
        public static readonly PropertyData ParentReportNodeIdProperty = RegisterProperty("ParentReportNodeId", typeof(int), default(int));

        public string NodeText
        {
            get { return GetValue<string>(NodeTextProperty); }
            set { SetValue(NodeTextProperty, value); }
        }
        public static readonly PropertyData NodeTextProperty = RegisterProperty("NodeText", typeof(string), default(string));

        public int SortOrder
        {
            get { return GetValue<int>(SortOrderProperty); }
            set { SetValue(SortOrderProperty, value); }
        }
        public static readonly PropertyData SortOrderProperty = RegisterProperty("SortOrder", typeof(int), default(int));

        public bool IsExportable
        {
            get { return GetValue<bool>(IsExportableProperty); }
            set { SetValue(IsExportableProperty, value); }
        }
        public static readonly PropertyData IsExportableProperty = RegisterProperty("IsExportable", typeof(bool), default(bool));

        public bool IsDeleted
        {
            get { return GetValue<bool>(IsDeletedProperty); }
            set { SetValue(IsDeletedProperty, value); }
        }
        public static readonly PropertyData IsDeletedProperty = RegisterProperty("IsDeleted", typeof(bool), default(bool));

        public bool IsSelected
        {
            get { return GetValue<bool>(IsSelectedProperty); }
            set { SetValue(IsSelectedProperty, value); }
        }
        public static readonly PropertyData IsSelectedProperty = RegisterProperty("IsSelected", typeof(bool), default(bool));

        public bool IsEnabled
        {
            get { return GetValue<bool>(IsEnabledProperty); }
            set { SetValue(IsEnabledProperty, value); }
        }
        public static readonly PropertyData IsEnabledProperty = RegisterProperty("IsEnabled", typeof(bool), default(bool));

        public bool IsInEditMode
        {
            get { return GetValue<bool>(IsInEditModeProperty); }
            set { SetValue(IsInEditModeProperty, value); }
        }
        public static readonly PropertyData IsInEditModeProperty = RegisterProperty("IsInEditMode", typeof(bool), default(bool));

        public bool IsExpanded
        {
            get { return GetValue<bool>(IsExpandedProperty); }
            set { SetValue(IsExpandedProperty, value); }
        }
        public static readonly PropertyData IsExpandedProperty = RegisterProperty("IsExpanded", typeof(bool), default(bool));


        //--------------------------------------------------------------------------------
        // [constructors]
        //--------------------------------------------------------------------------------

        public ReportItem()
        {
            Messages = new List<Message>();
        }


        //--------------------------------------------------------------------------------
        // [methods]
        //--------------------------------------------------------------------------------

        protected override void ValidateFields(List<IFieldValidationResult> validationResults)
        {

        }
    }

Jul 23, 2012 at 2:25 PM

Hi,

I've got it to work.

I had to mark UserData with [Model] attribute like so:

public class ObservableNodeViewModel : ViewModelBase
    {
        //--------------------------------------------------------------------------------
        // [constructors]
        //--------------------------------------------------------------------------------
 
        public ObservableNodeViewModel(ObservableNode<ReportItem> observableNode)
        {
            ObservableNodeReportItem = observableNode ?? new ObservableNode<ReportItem>();
        }
 
 
        //--------------------------------------------------------------------------------
        // [properties]
        //--------------------------------------------------------------------------------
 
        public override string Title { get { return "ObservableNodeReportItem window title"; } }
 
        [Model]
        public ObservableNode<ReportItem> ObservableNodeReportItem
        {
            get { return GetValue<ObservableNode<ReportItem>>(ObservableNodeReportItemProperty); }
            private set { SetValue(ObservableNodeReportItemProperty, value); }
        }
        public static readonly PropertyData ObservableNodeReportItemProperty = RegisterProperty("ObservableNodeReportItem"typeof(ObservableNode<ReportItem>));
 
        [Model]
        [ViewModelToModel("ObservableNodeReportItem""UserData")]
        public ReportItem UserData
        {
            get { return GetValue<ReportItem>(UserDataProperty); }
            set { SetValue(UserDataProperty, value); }
        }
        public static readonly PropertyData UserDataProperty = RegisterProperty("UserData"typeof(ReportItem));
    }
Coordinator
Jul 23, 2012 at 5:36 PM

Great to hear that you solved it on your own. Thanks for letting us know!