Deleting A Silverlight DataGrid Row With A Button On The Row
Aug
7
Written by:
8/7/2010 10:50 PM
NOTE: If you feel that this is way too complicated, you can use the method described here: "A Simple DataGrid Delete Button Using View Model / MVVM". The difference is that you would not have a Delete Button on each row.

Download the code: [at this link]
The topic of this blog may not seem like such a big deal unless you tried to do it. I demonstrated a method to raise an ICommand in the tutorial “Using The Silverlight DataGrid with View Model”, however what that does is insatiates a second copy of the main View Model.
You can call the ICommand, (for example to delete a record), and it will work. the problem is, that if you want to then remove the record from the DataGrid, you will discover that you can’t, because the View Model that you instantiated, is not connected to the .xaml page that the UI is on.
Dan Wahlin covers this in detail, if you’re still confused on what the problem is. He also has a solution that may also work for you.
The Problem
- We need to call a ICommand in a DataGrid, to delete an RIAComment.
- We need to remove the RIAComent from the collection the DataGrid is bound to (so it disappears).
The Solution
- We “wrap” the collection of RIAComments into a Wrapper Class.
- In the Wrapper Class, we add an ICommand to delete the RIAComment, and also add the code to call the web service, to actually perform the deletion.
- We create a Property in the Wrapper Class, to store an instance of the main View Model, so we can update the collection the DataGrid is bound to (and make the comment disappear).
The Details

First we make a class called RIACommentsCollectionWrapper. Basically it’s exactly like a normal View Model. The only difference is that we have these properties:
- objMainPageModel – This property will hold an instance of our main View Model and allow us to communicate with it.
- DeleteRIAComment – This is a normal ICommand that will be called by the Delete button. All the code to actually call the web service and delete the RIAComment is also in this class.
- objRIAComment – This is the actual RIAComment object that would normally be in a collection bound to the DataGrid.

We update the Web Service to add a DeleteRIAComment method:
#region DeleteRIAComment
[WebMethod]
public RIAComment DeleteRIAComment(int RIACommentID)
{
RIATasksDBDataContext DB = new RIATasksDBDataContext();
RIAComment ReturnRIAComment = new RIAComment();
ReturnRIAComment.CommentID = RIACommentID;
var result = (from RIAComments in DB.RIAComments
where RIAComments.CommentID == RIACommentID
select RIAComments).FirstOrDefault();
DB.RIAComments.DeleteOnSubmit(result);
DB.SubmitChanges();
return ReturnRIAComment;
}
#endregion
(note, sorting will work, but it was taken out of the original code example to reduce the code complexity)
Wrapping the RIAComments in the Wrapper Class
In the main View Model, we alter the RIACommments collection to use the Wrapper Class, (RIACommentsCollectionWrapper), instead of just RIAComments:
#region colRIAComments
private ObservableCollection _colRIAComments
= new ObservableCollection();
public ObservableCollection colRIAComments
{
get { return _colRIAComments; }
private set
{
if (colRIAComments == value)
{
return;
}
_colRIAComments = value;
this.NotifyPropertyChanged("colRIAComments");
}
}
#endregion
When we retrieve the RIAComments from the web service, we wrap them in the Wrapper Class:
// loop thru each item
foreach (var RIAComment in EventArgs.Result)
{
// Make a instance ofthe Wrapper
RIACommentsCollectionWrapper Wrapper = new RIACommentsCollectionWrapper();
// Add the RIAComment to the Wrapper
Wrapper.objRIAComment = RIAComment;
// Add an instance of this Main ViewModel to the Wrapper
Wrapper.objMainPageModel = this;
// Add the Wrapper to the collection that the DataGrid will be bound to
colRIAComments.Add(Wrapper);
}
All code that needs to reefer to the RIAComments collection, now needs to go through the Wrapper Class:
#region GetRIACommentCommand
public ICommand GetRIACommentCommand { get; set; }
public void GetRIAComment(object param)
{
GetRIAComment((param as RIACommentsCollectionWrapper).objRIAComment);
}
private bool CanGetRIAComment(object param)
{
return true;
}
#endregion
The View – Expression Blend

In Expression Blend, we are able to create sample data and bind to the RIAComments.

The only difference, is that we have to navigate through the Wrapper Class, to bind to the properties we want.

When we edit the column that the Button is on, in the DataGrid…

… and select it…

We click the New button next to it’s DataContext.

We set it’s DataContext to the Wrapper Class, (RIACommentsCollectionWrapper).
Note that this means we are creating a second copy of the Wrapper Class. We would not be able to update the main View Model if we did not have the “objMainPageModel” property.

Now when we drop a InvokeCommandAction Behavior on the button, we will be able to call the ICommand in the Wrapper Class that will delete the RIAComment.
Deleting The RIAComment From The DataGrid
In the Wrapper Class, this is the code that calls the Web Service to delete the RIAComment, and to remove it from the collection on the main View Model so it disappears on the DataGrid.
Note that where you see “objMainPageModel”, the code to calling the main View Model:
#region DeleteRIAComment
private void DeleteRIAComment(int CommentID)
{
// Call the Model to UpdateRIAComment the RIAComment
RIACommentsModel.DeleteRIAComment(CommentID, (Sender, EventArgs) =>
{
if (EventArgs.Error == null)
{
// Find the comment
var CommentInCollection =
(from comment in objRIACommentsCollectionWrapper.objMainPageModel.colRIAComments
where comment.objRIAComment.CommentID == EventArgs.Result.CommentID
select comment).FirstOrDefault();
if (CommentInCollection != null)
{
// Remove it
objRIACommentsCollectionWrapper.objMainPageModel.colRIAComments.Remove(CommentInCollection);
}
// Show any errors
objRIACommentsCollectionWrapper.objMainPageModel.Errors =
EventArgs.Result.Errors;
// Set the visibility of the Message ListBox
MessageVisibility = (objRIACommentsCollectionWrapper.objMainPageModel.Errors.Count > 0) ?
Visibility.Visible : Visibility.Collapsed;
}
});
}
#endregion
In Summary
When we set the DatContext of the Delete Button, we are creating a second instance of the Wrapper Class.
The only reason we are able to delete the RIAComment from the collection that is bound to the DataGrid, is that we have a Property in that class, (objMainPageModel), that stores an instance of the main View Model.