This is a migrated thread and some comments may be shown as answers.

Selection gets stuck when changing data from code

6 Answers 203 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Kalle Kula
Top achievements
Rank 1
Kalle Kula asked on 10 Jun 2010, 06:23 PM

I recently downloaded the WPF Trial package 2010 Q2 SP2 since we’ll probably be using that at work. I did with a separate branch of our code that is currently in development and is currently using a WPF Toolkit grid with row details which the customers don’t really like since they want a nice looking “tree grid”.

I very quickly replaced the grid with a RadGridView using a HierarchicalChildTemplate and got it up and running very nice in less than 30 minutes. We showed it to our customers to show them what might be possible and they got really impressed both by the looks, the child level functionality and especially the grouping/filtering/sorting that existed out of the box.

When showing/testing it we only used already existing data and didn’t change the data.

So I happily started yesterday with changing a couple of more grids and then started to run the application and immediately got stuck with rows not getting unselected after being edited by code.

After spending almost a day without understanding what I do wrong even with the smallest example without hierarchy I thought I should try to ask for an explanation here.

What I have in my small sample app is an Order entity that implements INotifyPropertyChanged for its properties.

A PresentationModel class also implementing INotifyPropertyChanged that pretty much consists of an ObservableCollection<Order>.

In the code behind of the xaml window I set the DataContext of the window to a new instance of the PresentationModel and create a list with four orders (with different data that makes both the Equals and GetHashCode return different values for each order).

Then I create a RadGridView in XAML and bind it like this:

<telerik:RadGridView x:Name="orderGrid" ItemsSource="{Binding Orders}"/>

I also added a button to the XAML file where I loop through the SelectedItems like this:

foreach (Order order in orderGrid.SelectedItems)

{

    order.Customer = "Kalle";

}

 

When run the application select a row and press the button the Customer column gets nicely updated to Kalle, but when I select another row the first one stays selected and I can’t find any way to get it out of the SelectedItems collection. If I Ctrl-click the row to unselect it and select another row it looks like just the other row is selected, but the SelectedItems still contains also the changed row no matter what I do. If I select yet another row and press the button also both of the rows gets set to Kalle and then both are stuck selected.

 

I guess I must be doing something completely stupid or missing something obvious because I don’t find anyone else on the forums that are experiencing this and binding to an ObservableCollection with custom entities and changing data by code can’t be an uncommon scenario.

6 Answers, 1 is accepted

Sort by
0
Veselin Vasilev
Telerik team
answered on 11 Jun 2010, 07:13 AM
Hello Kalle Kula,

This is indeed strange.
Can you try setting the SelectionMode property of the gridview to Single.
Another thing you can try is setting the IsSynchronizedWithCurrentItem to False.

Let us know how it goes.

Best wishes,
Veskoni
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kalle Kula
Top achievements
Rank 1
answered on 11 Jun 2010, 11:15 AM
Hi,

I can't say that helped. I tried different selectionmodes and with IsSynchronizedWithCurrentItem true or false and it behaves the same. Actually I noticed it also does when I manually edit the data in the cell when I didn't have it readonly flag set.

Do I need to do something else like handling events, BeginEdit/CommitEdit or things like that? With the WPFToolkit grid the binding was enough and I hoped it would be the same with this grid.

It seems only pictures are allowed as attachments so I'll paste my code below. What happens when I run it the selecteditems count (that I display in a label) match what is selected and selecting other rows unselects what was selected before and everything looks ok. But as soon as the button is pressed which changes the "customer" of the selected rows these rows stays selected no matter if you have single selection mode or not and even if you in extended mode ctrl-click on them to unselect them they still remain in the SelectedItems collection which to me seem like a very strange behavior.

Unless I've missed committing or something that makes the rows with pending changes to remain selected. But I've tried with CommitEdit and stuff and it doesn't seem to help...

The code (built in Visual Studio 2010 for .NET Framework 3.5):
SimpleGrid.xaml:
<Window x:Class="TelerikGridTest.CustomHierarchy" 
        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" 
        Title="MainWindow" Height="350" Width="525">  
    <StackPanel> 
        <telerik:RadGridView x:Name="orderGrid" ItemsSource="{Binding Orders}" SelectionMode="Extended" /> 
        <telerik:RadButton Content="Change customer" Click="RadButton_Click" /> 
        <Label Content="{Binding ElementName=orderGrid, Path=SelectedItems.Count}"></Label> 
    </StackPanel> 
</Window> 

SimpleGrid.xaml.cs:
using System.Collections.ObjectModel;  
using System.Windows;  
using Telerik.Windows.Controls;  
 
namespace TelerikGridTest  
{  
    public partial class CustomHierarchy : Window  
    {  
        public CustomHierarchy()  
        {  
            InitializeComponent();  
 
            Model = new PresentationModel { Orders = CreateOrders() };  
        }  
 
        private static ObservableCollection<Order> CreateOrders()  
        {  
            var orders = new ObservableCollection<Order>  
                             {  
                                 new Order {Id = 0, OrderNumber = 1, Customer = "Customer A", Amount = 10m},//, OrderRows = new ObservableCollection<OrderRow>()},  
                                 new Order {Id = 0, OrderNumber = 2, Customer = "Customer B", Amount = 20m},//, OrderRows = new ObservableCollection<OrderRow>()},  
                                 new Order {Id = 0, OrderNumber = 3, Customer = "Customer C", Amount = 30m},//, OrderRows = new ObservableCollection<OrderRow>()},  
                                 new Order {Id = 0, OrderNumber = 4, Customer = "Customer D", Amount = 40m}//, OrderRows = new ObservableCollection<OrderRow>()}  
                             };  
            return orders;  
        }  
 
        public PresentationModel Model  
        {  
            get { return DataContext as PresentationModel; }  
            set { DataContext = value; }  
        }  
 
        private void RadButton_Click(object sender, RoutedEventArgs e)  
        {  
            foreach (Order order in orderGrid.SelectedItems)  
            {  
                order.Customer = "Kalle";  
            }  
        }  
    }  
}  
 

PresentationModel.cs:
using System.Collections.ObjectModel;  
using System.ComponentModel;  
 
namespace TelerikGridTest  
{  
    public class PresentationModel : INotifyPropertyChanged  
    {  
        public event PropertyChangedEventHandler PropertyChanged;  
 
        private ObservableCollection<Order> orders;  
        public ObservableCollection<Order> Orders  
        {  
            get { return orders; }  
            set 
            {  
                orders = value;  
                OnPropertyChanged("Orders");  
            }  
        }  
 
        public object SelectedValue { getset; }  
 
        protected virtual void OnPropertyChanged(string propertyName)  
        {  
            var handler = PropertyChanged;  
            if (handler != null)  
                handler(thisnew PropertyChangedEventArgs(propertyName));  
        }  
 
    }  
}  
 

Order.cs:
using System.Collections.ObjectModel;  
using System.ComponentModel;  
 
namespace TelerikGridTest  
{  
    public class Order : INotifyPropertyChanged  
    {  
        public event PropertyChangedEventHandler PropertyChanged;  
          
        public int Id { getset; }  
        public int OrderNumber { getset; }  
        public string customer;  
        public string Customer { get { return customer; } set { customer = value; OnPropertyChanged("Customer"); } }  
        public decimal Amount { getset; }  
        public string DisplayAmount { get { return string.Format("{0} SEK", Amount); } }  
 
        public override bool Equals(object obj)  
        {  
            if (ReferenceEquals(null, obj)) return false;  
            if (ReferenceEquals(this, obj)) return true;  
            return obj.GetType() == typeof (Order) && Equals((Order) obj);  
        }  
 
        public bool Equals(Order other)  
        {  
            if (ReferenceEquals(null, other)) return false;  
            if (ReferenceEquals(this, other)) return true;  
            return other.Id == Id && other.OrderNumber == OrderNumber && other.Amount == Amount && Equals(other.Customer, Customer);  
        }  
 
        public override int GetHashCode()  
        {  
            unchecked 
            {  
                int result = Id;  
                result = (result * 397) ^ OrderNumber;  
                result = (result * 397) ^ Amount.GetHashCode();  
                result = (result * 397) ^ (Customer != null ? Customer.GetHashCode() : 0);  
                return result;  
            }  
        }  
 
        public void OnPropertyChanged(string name)  
        {  
            if (PropertyChanged != null)  
                PropertyChanged(thisnew PropertyChangedEventArgs(name));  
        }  
    }  
}  
 
0
Kalle Kula
Top achievements
Rank 1
answered on 16 Jun 2010, 08:32 AM
I've not had much time earlier this week to look into this, but was planning to try to migrate over parts of our application from WPFToolkit grids to RadGridViews today since our customers got really impressed when I showed them a demo when I changed one of our current screens using a WPFToolkit grid with rowdetails for a hierarchical RadGridView bound according to the Custom Hierarchy Template in the demo towards a datasource that is set up like in my code above.

It was very quick and easy to switch to the RadGridView and everything worked fine as long as I didn't edit any data, but when trying to change data from code it started to behave as previously described that it doesn't release edited rows from the SelectedItems collection even though you change your selection.

I still haven't been able to figure out why. As I stated it seems like a very strange behavior to hold on to the edited rows as selected even though they're not. Even when I run Single selection mode the SelectedItems collection contains several rows.

I would be really glad to get some input on whether this is a bug (and in that case when I can expect it to be fixed) or if it's just me missing something obvious.
0
Veselin Vasilev
Telerik team
answered on 16 Jun 2010, 11:53 AM
Hi Kalle Kula,

I tried to reproduce the problem, but to no avail.
Please find attached my sample VS 2010 project. Let me know if you manage to reproduce it.

Greetings,
Veskoni
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0
Kalle Kula
Top achievements
Rank 1
answered on 16 Jun 2010, 11:07 PM
Thanks for the sample project. As you said it worked perfect even if I change to use a presentationmodel and bind in XAML instead of as in your example in the codebehind.

With the help of your sample project I was finally able to pinpoint the problem. It seemed to be our ReSharper generated GetHashCode methods. When I commented out that it behaved perfectly fine.

Since we want custom Equals method on our entities we let ReSharper generate equality members and get GetHashCode methods similar to in your example. I'm not really sure why those cause the RadGridView to go crazy since they worked in the WPFToolkit grid, but it's nice to finally be able to try out the Telerik kit.

At all being able to have multiple SelectedItems when SelectionMode=Single seemed very strange (and still kinda does), but what the heck. I'm very happy right now.

Actually I've been sitting at home all evening converting parts of our application in a separate branch to be able to demonstrate it for the customer in a better way on our sprint demo tomorrow and I'm very impressed by the filtering/grouping capabilities of the RadGridView, and also changing TabControls, Buttons, ComboBoxes, DatePickers, RadioButtons etc makes a much more professional look of the application.

Thank you :-)
0
Milan
Telerik team
answered on 17 Jun 2010, 06:31 AM
Hello Kalle Kula,

Thank you very much for your interest in our controls. We are happy that the issues are now resolved and we would love to have you as a customer.

In regard to the strange selection behavior, internally we store a dictionary of all selected items and if two items have the same hash code and their Equals method dictates that they are indeed the same we will also consider them as one and the same object - in such situations the selection mechanism does not work very well. 

I agree that having the ability to add several items to SelectedItems collection in Single selection mode is strange and I would like to inform you that this is a know issue and we will fix it in a future release. If this issue hinders your work we could raise its priority.


Regards,
Milan
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
Tags
GridView
Asked by
Kalle Kula
Top achievements
Rank 1
Answers by
Veselin Vasilev
Telerik team
Kalle Kula
Top achievements
Rank 1
Milan
Telerik team
Share this question
or