I am working on wpf application with MVVM pattern. I have telerik grid containg categories of business objects ( categoryid, category number, category name). I allow user to inline gridview editing. I have managed to update, delete categories as i expected. When user add new category, user will enter category name and will save the record to database. Gridview selected item is binding with CurrentCateogry property in viewmodel and every time selection changes it will update the currenty category in the viewmodel. After user updated the record, corresponding category will save to database and generate new categoryid and category number and passes to the UI. Above all, corresponding selected item will not updating with new values though it has updated the current category property in viewmodel.
I have attached code samples as follows.
Category.cs
==========
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Data;
using
System.IO;
using
System.ComponentModel;
using
System.Data.SqlClient;
namespace
RadGridSelectedItemBindingTwoWay
{
public class Category : INotifyPropertyChanged
{
private Int32 _CategoryId;
private string _CategoryNumber;
private string _CategoryName;
public Category()
{
this.CategoryId = -1;
this.CategoryNumber = String.Empty;
this.CategoryName = String.Empty;
}
public Category(Int32 CategoryId, string CategoryNumber, string CategoryName)
{
this.CategoryId = CategoryId;
this.CategoryNumber = CategoryNumber;
this.CategoryName = CategoryName;
}
public Int32 CategoryId
{
get
{
return _CategoryId;
}
set
{
_CategoryId =
value;
OnPropertyChanged(
"CategoryId");
}
}
public string CategoryNumber
{
get
{
return _CategoryNumber;
}
set
{
_CategoryNumber =
value;
OnPropertyChanged(
"CategoryNumber");
}
}
public string CategoryName
{
get
{
return _CategoryName;
}
set
{
_CategoryName =
value;
OnPropertyChanged(
"CategoryName");
}
}
public override string ToString()
{
string CategoryString = String.Empty;
CategoryString =
this.CategoryName;
return CategoryString;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
MainWindow.xaml
=============
<
Window x:Class="RadGridSelectedItemBindingTwoWay.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:telerikGrid="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView"
xmlns:nav="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"
xmlns:RadBind="clr-namespace:RadGridSelectedItemBindingTwoWay"
Title="RadGridView - Selected Item Binding Two Way - MVVM" Height="350" Width="525">
<Grid>
<StackPanel Grid.Row="0" Grid.Column="0" Margin="10,10" >
<nav:RadTabControl>
<nav:RadTabItem Header="Category">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="40*"/>
</Grid.RowDefinitions>
<telerik:RadDataPager Grid.Row="0" PageSize="20" Source="{Binding Items, ElementName=CategoryRadGridView}"
IsTotalItemCountFixed="False" DisplayMode="FirstLastPreviousNextNumeric, Text"
/>
<telerikGrid:RadGridView Grid.Row="1" x:Name="CategoryRadGridView" GridLinesVisibility="Horizontal"
AutoGenerateColumns="False" SelectionMode="Single"
RowIndicatorVisibility="Hidden" IsReadOnly="False"
CanUserFreezeColumns="False" ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ShowGroupPanel="False"
ItemsSource="{Binding Categories}"
ActionOnLostFocus="None"
SelectedItem="{Binding Path=CurrentCategory, UpdateSourceTrigger=Explicit,Mode=TwoWay}"
KeyboardNavigation.AcceptsReturn="True"
>
<telerikGrid:RadGridView.Columns>
<telerikGrid:GridViewDataColumn DataMemberBinding="{Binding CategoryId, Mode=TwoWay}" Header="Category Id" IsReadOnly="True" IsVisible="True" />
<telerikGrid:GridViewDataColumn DataMemberBinding="{Binding CategoryNumber, Mode=TwoWay}" Header="Category Number" Width="300*" IsReadOnly="True"/>
<telerikGrid:GridViewDataColumn DataMemberBinding="{Binding CategoryName, Mode=TwoWay}" Header="Category Name" IsVisible="True" />
<telerikGrid:GridViewDataColumn >
<telerikGrid:GridViewColumn.CellTemplate>
<DataTemplate>
<telerik:RadButton x:Name="Category_SaveRow" HorizontalAlignment="Stretch"
ToolTip="Update" Content="Update"
Command="{Binding Path=CategorySaveCommand}"
Loaded="Category_SaveRow_Loaded"
Click="Category_SaveRow_Click">
</telerik:RadButton>
</DataTemplate>
</telerikGrid:GridViewColumn.CellTemplate>
</telerikGrid:GridViewDataColumn>
 
<telerikGrid:GridViewDataColumn >
<telerikGrid:GridViewColumn.CellTemplate>
<DataTemplate>
<telerik:RadButton x:Name="Category_RemoveRow" HorizontalAlignment="Stretch"
ToolTip="Delete" Content="Delete"
Command="{Binding Path=CategoryDeleteCommand}"
Loaded="Category_RemoveRow_Loaded"
Click="Category_RemoveRow_Click"
>
</telerik:RadButton>
</DataTemplate>
</telerikGrid:GridViewColumn.CellTemplate>
</telerikGrid:GridViewDataColumn>
</telerikGrid:RadGridView.Columns>
</telerikGrid:RadGridView>
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="5">
<telerik:RadButton Grid.Row="2" Content="Add Category" Width="100" Margin="5,5"
Command="telerikGrid:RadGridViewCommands.BeginInsert" CommandTarget="{Binding ElementName=CategoryRadGridView}"/>
<telerik:RadButton Grid.Row="2" Content="Cancel" Width="100" Margin="5,5"
Command="telerikGrid:RadGridViewCommands.CancelRowEdit" CommandTarget="{Binding ElementName=CategoryRadGridView}"/>
</StackPanel>
</Grid>
 
</nav:RadTabItem>
</nav:RadTabControl>
</StackPanel>
</Grid>
</
Window>
MainWindowCS
-------------------
using
System.Windows;
using
System.Windows.Controls;
using
Telerik.Windows.Controls;
namespace
RadGridSelectedItemBindingTwoWay
{
public partial class MainWindow : Window
{
MyViewModel _MyViewModel;
public MainWindow()
{
InitializeComponent();
_MyViewModel =
new MyViewModel();
this.DataContext = _MyViewModel;
}
private void Category_SaveRow_Loaded(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
button.Command = _MyViewModel.CategorySaveCommand;
}
private void Category_SaveRow_Click(object sender, RoutedEventArgs e)
{
// TODO : Explicitly set current category of the view model
_MyViewModel.CurrentCategory = (
Category)((RadButton)sender).DataContext;
this.CategoryRadGridView.CommitEdit();
}
private void Category_RemoveRow_Loaded(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
button.Command = _MyViewModel.CategoryDeleteCommand;
}
private void Category_RemoveRow_Click(object sender, RoutedEventArgs e)
{
_MyViewModel.CurrentCategory = (
Category)((RadButton)sender).DataContext;
}
}
}
MyViewModel :
------------------
using
System;
using
System.Collections.ObjectModel;
using
System.ComponentModel;
using
System.Windows.Input;
using
RadGridSelectedItemBindingTwoWay.Model;
 
namespace
RadGridSelectedItemBindingTwoWay
{
public class MyViewModel : INotifyPropertyChanged
{
private ObservableCollection<Category> _Categories; // trigger category updates
private DelegateCommand _CategorySaveCommand; // Handle category save as delegate command
private DelegateCommand _CategoryDeleteCommand;// Handle cateogry delete as delegate command
 
private Category _CurrentCategory;
 
public MyViewModel()
{
this.Categories = GetComponentCategories();
// Initialize the delegate commands
_CategorySaveCommand =
new DelegateCommand(CategorySave);
_CategoryDeleteCommand =
new DelegateCommand(CategoryDelete);
}
 
 
 
public ObservableCollection<Category> Categories
{
get
{
return _Categories;
}
set
{
_Categories =
value;
this.OnPropertyChanged("Categories");
}
}
public ICommand CategorySaveCommand
{
get
{
if (_CategorySaveCommand == null)
{
_CategorySaveCommand =
new DelegateCommand(CategorySave);
}
return this._CategorySaveCommand;
}
}
public ICommand CategoryDeleteCommand
{
get
{
if (_CategoryDeleteCommand == null)
{
_CategoryDeleteCommand =
new DelegateCommand(CategoryDelete);
}
return this._CategoryDeleteCommand;
}
}
public Category CurrentCategory
{
get
{
return this._CurrentCategory;
}
set
{
this._CurrentCategory = value;
this.OnPropertyChanged("CurrentCategory");
}
}
 
 
private ObservableCollection<Category> GetComponentCategories()
{
ObservableCollection<Category> categoryOC = new ObservableCollection<Category>();
categoryOC.Add(
new Category(1, "000001", "Category1"));
categoryOC.Add(
new Category(2, "000002", "Category2"));
categoryOC.Add(
new Category(3, "000003", "Category3"));
return categoryOC;
}
 
 
public void CategorySave()
{
// Save to database and generate category id and category number and will return to the UI layer
Category SavedCategory = SaveCategoryToDatabaseAndReturnSavedCategory(this.CurrentCategory);
this.CurrentCategory = SavedCategory; // I am expecting to see save category id and catgory number as selected
// item is binding with current category property but not updated the UI with new values
}
private void CategoryDelete()
{
this.Categories.Remove(this.CurrentCategory);
}
private Category SaveCategoryToDatabaseAndReturnSavedCategory(Category toSaveCategory)
{
// Temp method to category to database and generate sequential new category id and category number
Category newCategory = new Category();
Random random = new Random();
newCategory.CategoryId = random.Next(100);
newCategory.CategoryNumber = newCategory.CategoryId.ToString();
newCategory.CategoryName = toSaveCategory.CategoryName;
return newCategory;
}
#region
INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
//protected virtual void OnPropertyChanged(string propertyName)
//{
// if (null != this.PropertyChanged)
// {
// this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
// }
//}
//protected virtual void NotifyPropertyChanged(string propertyname)
//{
// if (PropertyChanged != null)
// {
// PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
// }
//}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(
this, args);
}
}
private void OnPropertyChanged(string propertyName)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
Command
-------------
public
class DelegateCommand : ICommand
{
private Action _executeMethod;
public DelegateCommand(Action executeMethod)
{
_executeMethod = executeMethod;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_executeMethod.Invoke();
}
}
Thanking You..