This question is locked. New answers and comments are not allowed.
I've been implementing sucessfully the QueryableDataServiceCollectionView using a fully functional MVVM pattern.
I have a gridview, pager and a set of buttons (Save, Reject, Refresh) implementing the ICommand (with the CanExecute) so that they can automatically deactivate/active based on the CollectionView status property HasChanges.
Somehow, this works perfectly until i try to insert a new row using the RadGridView's builtin insert pivot row.
After i insert a record using the above method, the HasChanges property on the QueryableDataServiceCollectionView never gets updated again, even if I update some records.
My goal is to allow to user to produce a set of changes and then use the Submit or Reject changes in the CollectionView.
Facts:
All the CRUD operations are done using the RadGridView's builtin UI operations, there is no code involved for CRUD operations.
This behavior is happening without ever calling SubmitChanges, so there is no server interaction involved in this process.
I can successfully reproduce this behavior by executing the following steps:
1. Edit a row using the RadGridView's builtin edit feature (double click on the cell) and commit the changes to the CollectionView by pressing Enter. Notice that the HasChanges property has changed to True.
2. Undo the operation by calling RejectChanges on the CollectionView. Notice that the HasChanges property has changed to False.
3. Insert a new row using the RadGridView's builtin insert feature (ShowInsertRow="True") and commit the changes to the CollectionView by pressing Enter. Notice that the HasChanges property has changed to True.
4. Undo the operation by calling RejectChanges on the CollectionView. Notice that the HasChanges property has changed to False.
5. After this step, the CollectionView is somehow broken because the HasChanges will never get changed again and will be allways defaulted to False. You can confirm this by making any change on the RadGridView (updating, inserting or deleting).
This is a issue in my case because it breaks the chain of my Save & Undo buttons making them to never get enabled again because the CanExecute event (ICommand) will allways return false, because HasChanges is allways false.
Here is my ViewModel:
I have a gridview, pager and a set of buttons (Save, Reject, Refresh) implementing the ICommand (with the CanExecute) so that they can automatically deactivate/active based on the CollectionView status property HasChanges.
Somehow, this works perfectly until i try to insert a new row using the RadGridView's builtin insert pivot row.
After i insert a record using the above method, the HasChanges property on the QueryableDataServiceCollectionView never gets updated again, even if I update some records.
My goal is to allow to user to produce a set of changes and then use the Submit or Reject changes in the CollectionView.
Facts:
All the CRUD operations are done using the RadGridView's builtin UI operations, there is no code involved for CRUD operations.
This behavior is happening without ever calling SubmitChanges, so there is no server interaction involved in this process.
I can successfully reproduce this behavior by executing the following steps:
1. Edit a row using the RadGridView's builtin edit feature (double click on the cell) and commit the changes to the CollectionView by pressing Enter. Notice that the HasChanges property has changed to True.
2. Undo the operation by calling RejectChanges on the CollectionView. Notice that the HasChanges property has changed to False.
3. Insert a new row using the RadGridView's builtin insert feature (ShowInsertRow="True") and commit the changes to the CollectionView by pressing Enter. Notice that the HasChanges property has changed to True.
4. Undo the operation by calling RejectChanges on the CollectionView. Notice that the HasChanges property has changed to False.
5. After this step, the CollectionView is somehow broken because the HasChanges will never get changed again and will be allways defaulted to False. You can confirm this by making any change on the RadGridView (updating, inserting or deleting).
This is a issue in my case because it breaks the chain of my Save & Undo buttons making them to never get enabled again because the CanExecute event (ICommand) will allways return false, because HasChanges is allways false.
Here is my ViewModel:
public class ImdbTitlesViewModel : ViewModelBase { private ImdbDataContext _imdbContext; private QueryableDataServiceCollectionView<ImdbTitle> _imdbTitlesView; public QueryableDataServiceCollectionView<ImdbTitle> ImdbTitlesView { get { return _imdbTitlesView; } } public IEnumerable<ImdbTitle> ImdbTitles { get { return this._imdbTitlesView; } } private ImdbTitle _selectedTitle; public ImdbTitle SelectedTitle { get { return this._selectedTitle; } set { if (this._selectedTitle != value) { this._selectedTitle = value; RaisePropertyChanged("SelectedTitle"); } } } private bool _isBusy; public bool IsBusy { get { return this._isBusy; } set { if (this._isBusy != value) { this._isBusy = value; RaisePropertyChanged("IsBusy"); } } } public RelayCommand Startup { get; set; } public RelayCommand Refresh { get { return LoadImdbTitles; } set { LoadImdbTitles = value; } } public RelayCommand LoadImdbTitles { get; set; } public RelayCommand SaveChanges { get; set; } public RelayCommand RejectChanges { get; set; } /// <summary> /// Initializes a new instance of the ImdbTitlesViewModel class. /// </summary> public ImdbTitlesViewModel() { Startup = new RelayCommand(OnStartup); LoadImdbTitles = new RelayCommand(OnLoadImdbTitles, CanLoadImdbTitles); SaveChanges = new RelayCommand(OnSaveChanges, CanSaveChanges); RejectChanges = new RelayCommand(OnRejectChanges, CanRejectChanges); if (IsInDesignMode) { // Code runs in Blend --> create design time data. } else { // Code runs "for real": Connect to service, etc... this._imdbContext = new ImdbDataContext(); this._imdbTitlesView = new QueryableDataServiceCollectionView<ImdbTitle>(this._imdbContext, this._imdbContext.ImdbTitles); this._imdbTitlesView.LoadedData += new EventHandler<Telerik.Windows.Controls.DataServices.LoadedDataEventArgs>(OnImdbTitlesViewLoadedData); this._imdbTitlesView.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(OnImdbTitlesViewPropertyChanged); this._imdbTitlesView.PageSize = 25; this._imdbTitlesView.AutoLoad = true; this._imdbTitlesView.SubmittedChanges += new EventHandler<Telerik.Windows.Controls.DataServices.DataServiceSubmittedChangesEventArgs>(OnImdbTitlesViewSubmittedChanges); } } void OnImdbTitlesViewSubmittedChanges(object sender, Telerik.Windows.Controls.DataServices.DataServiceSubmittedChangesEventArgs e) { if (e.HasError) { e.MarkErrorAsHandled(); MessageBox.Show(e.Error.Message, "Error occurred", MessageBoxButton.OK); } else { MessageBox.Show("Changes saved successfully!", "Notification", MessageBoxButton.OK); } } void OnImdbTitlesViewPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName.Equals("IsBusy")) { this.IsBusy = this._imdbTitlesView.IsBusy; } if(e.PropertyName.Equals("HasChanges")) { SaveChanges.RaiseCanExecuteChanged(); RejectChanges.RaiseCanExecuteChanged(); } } void OnImdbTitlesViewLoadedData(object sender, Telerik.Windows.Controls.DataServices.LoadedDataEventArgs e) { if (e.HasError) { e.MarkErrorAsHandled(); MessageBox.Show(e.Error.Message, "Error occurred", MessageBoxButton.OK); } } private void OnStartup() { // We dont need to startup because the DataView has the property AutoLoad = true //GetImdbTitles(); } private bool CanLoadImdbTitles() { return !IsBusy; } private void OnLoadImdbTitles() { // Execute the query. //this.RejectChanges.Execute(null); this._imdbTitlesView.Load(true); //this._imdbTitlesView.Load(true); } private bool CanSaveChanges() { if (this.IsBusy) return false; if (this._imdbTitlesView.HasChanges) return true; return false; } private void OnSaveChanges() { this._imdbTitlesView.SubmitChanges(); } private void OnRejectChanges() { this._imdbTitlesView.RejectChanges(); } private bool CanRejectChanges() { if (this.IsBusy) return false; if (this._imdbTitlesView.HasChanges) return true; else return false; } public override void Cleanup() { // Clean own resources if needed base.Cleanup(); } }