Sunday, October 5, 2008

Silverlight 2 RC0 DataGrid CommittingEdit work around

In Silverlight 2 Beta 2 DataGrid had a CommittingEdit event which was a great event to update the data in an ado.net dataservice.   Unfortunately this event was removed in the RC0 of the datagrid.  As a work around Jonathan Shen suggested using a template column and using the LostFocus event to update your dataservice data.


                 <data:DataGridTemplateColumn Header="Command">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding FirstName}"></TextBlock>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>
                        <data:DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate>
                                <TextBox Text="{Binding FirstName}"LostFocus="TextBox_LostFocus"></TextBox>   //you can detect other events.
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellEditingTemplate>
                    </data:DataGridTemplateColumn>

Well this works fine but I don't want to have to define all my columns this way.  Sometimes it is nice to just let the datagrid autogenerate the columns. So I decided to use the DataGrid's PreparingCellForEdit to add the handler for the LostFocus event.  Couple of other things you need to do.  First Remove the old event handler so the event does not fire multiple times.  Second we need a variable to keep track of the item that was edited when the lost focus event is fired we will be on another record.

Dim prod As Northwind.Products
Private Sub dgProducts_PreparingCellForEdit(ByVal sender As Object, ByVal e As System.Windows.Controls.DataGridPreparingCellForEditEventArgs) Handles dgProducts.PreparingCellForEdit
    RemoveHandler e.EditingElement.LostFocus, AddressOf Textbox_LostFocus
    AddHandler e.EditingElement.LostFocus, AddressOf Textbox_LostFocus
    prod = DirectCast(dgProducts.SelectedItem, Northwind.Products)
End Sub
Friend Sub Textbox_LostFocus(ByVal sender As Object, ByVal e As EventArgs)
    proxy.UpdateObject(prod)
End Sub

Here is the complete code

Imports System.Collections.ObjectModel
Imports System.Data.Services.Client
Imports System.Diagnostics
Partial Public Class Page
    Inherits UserControl
    Public Sub New()
        InitializeComponent()
    End Sub
    Dim q As DataServiceQuery(Of Northwind.Products)
    Dim proxy As Northwind.NorthwindEntities
    Private Sub Page_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        Dim address = New Uri(Application.Current.Host.Source, "../WebDataService1.svc")
        proxy = New Northwind.NorthwindEntities(address)
        Dim qry = From p In proxy.Products Select p
        q = CType(qry, Global.System.Data.Services.Client.DataServiceQuery(Of Northwind.Products))
        q.BeginExecute(AddressOf ProductsLoaded, Nothing)
    End Sub
    Friend Sub ProductsLoaded(ByVal ar As System.IAsyncResult)
        Dim c = q.EndExecute(ar)
        Dim d As New ObservableCollection(Of Northwind.Products)
        For Each p In c
            d.Add(p)
        Next
        Dim GetOnRightThread As New SetTheDataSource(AddressOf SetDataSource)
        Dispatcher.BeginInvoke(GetOnRightThread, New Object() {d})
    End Sub
    Delegate Sub SetTheDataSource(ByVal d As ObservableCollection(Of Northwind.Products))
    Friend Sub SetDataSource(ByVal d As ObservableCollection(Of Northwind.Products))
        dgProducts.ItemsSource = d
    End Sub
    Dim prod As Northwind.Products
    Private Sub dgProducts_PreparingCellForEdit(ByVal sender As Object, ByVal e As System.Windows.Controls.DataGridPreparingCellForEditEventArgs) Handles dgProducts.PreparingCellForEdit
        RemoveHandler e.EditingElement.LostFocus, AddressOf Textbox_LostFocus
        AddHandler e.EditingElement.LostFocus, AddressOf Textbox_LostFocus
        prod = DirectCast(dgProducts.SelectedItem, Northwind.Products)
    End Sub
    Friend Sub Textbox_LostFocus(ByVal sender As Object, ByVal e As EventArgs)
        proxy.UpdateObject(prod)
    End Sub
    Friend Sub SaveComplete(ByVal ar As System.IAsyncResult)
        proxy.EndSaveChanges(ar)
    End Sub
    Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles btnSave.Click
        proxy.BeginSaveChanges(AddressOf SaveComplete, Nothing)
    End Sub
End Class

No comments:

Post a Comment