RadControls for WPF Q3 2009.
I would like to know how best to represent two collections of data in two GridView controls.
We currently have situation where we have a collection of a data to be displayed and edited. The objects in this collection have additional collections of other data, also which need to be edited. (there are also cases where we have third level collections).
Currently we are forced to use WPF ListView controls to display this data, and edit them in TextBox/ComboBox fields. The ListView supports the IsSynchronizedWithCurrentItem property, which synchonises the ListViews at multiple levels of the Business Object.
From what I can tell, the RadGridView does not appear to support IsSynchronizedWithCurrentItem. I have attempted to use the SelectionChanged event on the RadGridView, with dissapointing results. On particular occasions when clearing the binding on the second RadGridView, I get an exception "Cannot change ObservableCollection during a CollectionChanged event".
This occurs when the user clears the Row selection, by holding down the Ctrl key, and clicks on the row on the second time. (Ie. Selects a row, unselects the row, selects a row, unselects the row.)
Is there a particular method or way that I can occomplish this?
Here is an example of the ListView, next to our partially functioning RadGridView.
I would like to know how best to represent two collections of data in two GridView controls.
We currently have situation where we have a collection of a data to be displayed and edited. The objects in this collection have additional collections of other data, also which need to be edited. (there are also cases where we have third level collections).
Currently we are forced to use WPF ListView controls to display this data, and edit them in TextBox/ComboBox fields. The ListView supports the IsSynchronizedWithCurrentItem property, which synchonises the ListViews at multiple levels of the Business Object.
From what I can tell, the RadGridView does not appear to support IsSynchronizedWithCurrentItem. I have attempted to use the SelectionChanged event on the RadGridView, with dissapointing results. On particular occasions when clearing the binding on the second RadGridView, I get an exception "Cannot change ObservableCollection during a CollectionChanged event".
This occurs when the user clears the Row selection, by holding down the Ctrl key, and clicks on the row on the second time. (Ie. Selects a row, unselects the row, selects a row, unselects the row.)
Is there a particular method or way that I can occomplish this?
Here is an example of the ListView, next to our partially functioning RadGridView.
<Grid> |
<Grid> |
<Grid.RowDefinitions> |
<RowDefinition/> |
<RowDefinition/> |
</Grid.RowDefinitions> |
<Grid.ColumnDefinitions> |
<ColumnDefinition/> |
<ColumnDefinition/> |
<ColumnDefinition/> |
<ColumnDefinition/> |
</Grid.ColumnDefinitions> |
<ListView Name="uxListView1" Grid.Column="1" Grid.Row="0"> |
<ListView.View> |
<GridView> |
<GridView.Columns> |
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" /> |
<GridViewColumn Header="City" DisplayMemberBinding="{Binding City}" /> |
<GridViewColumn Header="Country" DisplayMemberBinding="{Binding Country}" /> |
</GridView.Columns> |
</GridView> |
</ListView.View> |
</ListView> |
<ListView Name="uxListView2" Grid.Column="1" Grid.Row="1"> |
<ListView.View> |
<GridView> |
<GridView.Columns> |
<GridViewColumn Header="AreaCode" DisplayMemberBinding="{Binding AreaCode}" /> |
<GridViewColumn Header="Number" DisplayMemberBinding="{Binding Number}" /> |
</GridView.Columns> |
</GridView> |
</ListView.View> |
</ListView> |
<telerik:RadGridView xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" |
Grid.Column="3" Grid.Row="0" |
AutoGenerateColumns="False" CanUserFreezeColumns="False" |
CanUserSortColumns="True" |
CanUserInsertRows="True" |
ShowGroupPanel="False" |
x:Name="uxRad4GridView" UseAlternateRowStyle="False" telerik:StyleManager.Theme="Office_Black"> |
<telerik:RadGridView.Columns> |
<telerik:GridViewDataColumn IsFilterable="False" DataMemberBinding="{Binding Name}" /> |
<telerik:GridViewDataColumn IsFilterable="False" DataMemberBinding="{Binding City}"/> |
<telerik:GridViewDataColumn IsFilterable="False" DataMemberBinding="{Binding Country}"/> |
</telerik:RadGridView.Columns> |
</telerik:RadGridView> |
<telerik:RadGridView xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" |
Grid.Column="3" Grid.Row="1" |
AutoGenerateColumns="False" CanUserFreezeColumns="False" |
CanUserSortColumns="True" |
CanUserInsertRows="True" |
ShowGroupPanel="False" |
x:Name="uxRad5GridView" UseAlternateRowStyle="False" telerik:StyleManager.Theme="Office_Black"> |
<telerik:RadGridView.Columns> |
<telerik:GridViewDataColumn IsFilterable="False" DataMemberBinding="{Binding AreaCode}" /> |
<telerik:GridViewDataColumn IsFilterable="False" DataMemberBinding="{Binding Number}"/> |
</telerik:RadGridView.Columns> |
</telerik:RadGridView> |
</Grid> |
</Grid> |
using System.Collections.ObjectModel; |
using System.ComponentModel; |
public class Customer : INotifyPropertyChanged |
{ |
#region fields |
private string _name; |
private string _country; |
private string _city; |
private ObservableCollection<Phone> _phoneNumbers; |
#endregion |
#region ctor |
public Customer() |
{ |
_phoneNumbers = new ObservableCollection<Phone>(); |
} |
public Customer(string name, string country, string city) |
{ |
_name = name; |
_country = country; |
_city = city; |
_phoneNumbers = new ObservableCollection<Phone>(); |
} |
public Customer(string name, string country, string city, ObservableCollection<Phone> phoneNumbers) |
{ |
_name = name; |
_country = country; |
_city = city; |
_phoneNumbers = phoneNumbers; |
} |
#endregion |
#region properties |
public string Name |
{ |
get { return _name; } |
set |
{ |
_name = value; |
NotifyPropertyChanged("Name"); |
} |
} |
public string City |
{ |
get { return _city; } |
set |
{ |
_city = value; |
NotifyPropertyChanged("City"); |
} |
} |
public string Country |
{ |
get { return _country; } |
set |
{ |
_country = value; |
NotifyPropertyChanged("Country"); |
} |
} |
public ObservableCollection<Phone> PhoneNumbers |
{ |
get { return _phoneNumbers; } |
set |
{ |
_phoneNumbers = value; |
NotifyPropertyChanged("PhoneNumbers"); |
} |
} |
#endregion |
#region Interface INotifyPropertyChanged |
public event PropertyChangedEventHandler PropertyChanged; |
private void NotifyPropertyChanged(string propertyName) |
{ |
if (PropertyChanged != null) |
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); |
} |
#endregion |
} |
public class Phone : INotifyPropertyChanged |
{ |
#region fields |
private string _areaCode; |
private string _number; |
#endregion |
#region ctor |
public Phone() |
{ |
} |
public Phone(string areaCode, string number) |
{ |
_areaCode = areaCode; |
_number = number; |
} |
#endregion |
#region properties |
public string AreaCode |
{ |
get { return _areaCode; } |
set |
{ |
_areaCode = value; |
NotifyPropertyChanged("AreaCode"); |
} |
} |
public string Number |
{ |
get { return _number; } |
set |
{ |
_number = value; |
NotifyPropertyChanged("Number"); |
} |
} |
#endregion |
#region Interface INotifyPropertyChanged |
public event PropertyChangedEventHandler PropertyChanged; |
private void NotifyPropertyChanged(string propertyName) |
{ |
if (PropertyChanged != null) |
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); |
} |
#endregion |
} |
using System; |
using System.Collections.ObjectModel; |
using System.Windows; |
using System.Windows.Controls; |
using System.Windows.Data; |
using Telerik.Windows.Controls; |
/// <summary> |
/// Interaction logic for Window5.xaml |
/// </summary> |
public partial class Window5 : Window |
{ |
public Window5() |
{ |
InitializeComponent(); |
Binding binding; |
#region ListView. Works by using IsSynchronizedWithCurrentItem |
ObservableCollection<Customer> list2 = CreateList(); |
binding = new Binding(); |
binding.Source = list2; |
uxListView1.IsSynchronizedWithCurrentItem = true; |
uxListView1.SetBinding(ListView.ItemsSourceProperty, binding); |
binding = new Binding(); |
binding.Source = list2; |
binding.Path = new PropertyPath("PhoneNumbers"); |
uxListView2.IsSynchronizedWithCurrentItem = true; |
uxListView2.SetBinding(ListView.ItemsSourceProperty, binding); |
#endregion |
ObservableCollection<Customer> list4 = CreateList(); |
binding = new Binding(); |
binding.Source = list4; |
//uxRad4GridView.IsSynchronizedWithCurrentItem = true; // Doesn't seem to be supported. |
uxRad4GridView.SelectionChanged += new EventHandler<SelectionChangeEventArgs>(uxRad4GridView_SelectionChanged); // Using this instead of IsSynchronizedWithCurrentItem |
uxRad4GridView.SetBinding(RadGridView.ItemsSourceProperty, binding); |
/// No point in binding it, as IsSynchronizedWithCurrentItem isn't supported. |
//binding = new Binding(); |
//binding.Source = list4; |
//binding.Path = new PropertyPath("PhoneNumbers"); |
//uxRad5GridView.IsSynchronizedWithCurrentItem = true; // Doesn't seem to be supported. |
//uxRad5GridView.SetBinding(RadGridView.ItemsSourceProperty, binding); |
} |
void uxRad4GridView_SelectionChanged(object sender, SelectionChangeEventArgs e) |
{ |
/// When the user holds "ctrl" to unselect a row, we must clear the secondary Grid. |
/// This however causes an exception to occur the second time a Row is unselected. |
if (uxRad4GridView.SelectedItem == null) |
{ |
uxRad5GridView.ClearValue(RadGridView.ItemsSourceProperty); |
} |
else |
{ |
Binding binding = new Binding(); |
binding.Source = uxRad4GridView.SelectedItem; |
binding.Path = new PropertyPath("PhoneNumbers"); |
uxRad5GridView.SetBinding(RadGridView.ItemsSourceProperty, binding); |
} |
} |
private ObservableCollection<Customer> CreateList() |
{ |
ObservableCollection<Customer> customers = new ObservableCollection<Customer>(); |
customers.Add(new Customer("John", "USA", "Chicago", new ObservableCollection<Phone>(new Phone[] { new Phone("XX", "1234"), new Phone("XX", "5678") }))); |
customers.Add(new Customer("Tim", "USA", "NY", new ObservableCollection<Phone>(new Phone[] { new Phone("AA", "2345"), new Phone("AA", "6789") }))); |
customers.Add(new Customer("Jeff", "USA", "W.D.C", new ObservableCollection<Phone>(new Phone[] { new Phone("ZZ", "3456"), new Phone("ZZ", "7890") }))); |
customers.Add(new Customer("Zhang", "China", "Shanghai", new ObservableCollection<Phone>(new Phone[] { new Phone("BB", "4567"), new Phone("BB", "8901") }))); |
customers.Add(new Customer("Li", "China", "Beijing", new ObservableCollection<Phone>(new Phone[] { new Phone("YY", "5678"), new Phone("YY", "9012") }))); |
customers.Add(new Customer("Wang", "China", "HongKong", new ObservableCollection<Phone>(new Phone[] { new Phone("CC", "6789"), new Phone("CC", "0123") }))); |
return customers; |
} |
} |