<telerik:GridViewDataColumn Header="Type" DataMemberBinding="{Binding TypeCombo}"> |
<telerik:GridViewDataColumn.CellTemplate> |
<DataTemplate> |
<telerikInput:RadComboBox ItemsSource="{Binding TypeCombo.ItemsSource}" |
SelectedIndex="{Binding TypeCombo.SelectedIndex, Mode=TwoWay}" |
IsEnabled="{Binding IsComboTypeEnabled}"/> |
</DataTemplate> |
</telerik:GridViewDataColumn.CellTemplate> |
</telerik:GridViewDataColumn> |
18 Answers, 1 is accepted
This is a strange problem. Although the grid reuses some of its elements the DataContext for each item is kept in sync and you should not get incorrect values. Could you please send us your project so that we can observe the issue and try to provide a solution.
Regards,
Milan
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Do you have a solution ? I have the same issue...
Thanks in advance.
Best regards,
Pedro
Since this thread was more than a year ago can you post more info about the problem at your end the the grid version?
Vlad
the Telerik team
The grid ItemSource property is getting bound to a structure which is something like given below
public
const
string
RowDataPropertyName =
"RowData"
;
private
ObservableCollection<DetailsGridRowModel> m_RowData;
public
ObservableCollection<DetailsGridRowModel> RowData
{
get
{
return
m_RowData;
}
set
{
if
(m_RowData == value)
{
return
;
}
m_RowData = value;
OnNotifyPropertyChanged(RowDataPropertyName);
}
}
Here each column has a CellTemplate which contains a custom control.
.
.
.
int
i = 0;
foreach
(var col
in
ColumnsCollection)
{
GridViewDataColumn column =
new
GridViewDataColumn();
column.CellTemplate = GetDataboundTemplate(i);
// do something with col here
GridView.Columns.Add(column);
i++;
}
.
.
.
public
DataTemplate GetDataboundTemplate(
int
columnIndex)
{
StringBuilder xaml =
new
StringBuilder();
xaml.Append(
"<DataTemplate xmlns=\" [namespace] \" xmlns:my=\" [namespace] \">"
);
xaml.Append(
"<my:DetailsGridItemView Context=\"{Binding ColumnData["
+ columnIndex +
"]}\" />"
);
xaml.Append(
"</DataTemplate>"
);
DataTemplate template = XamlReader.Load(xaml.ToString())
as
DataTemplate;
return
template;
}
The DetailsGridItemView control uses the Context property to render itself correctly.
The correct behavior for the grid is to bind each row to an instance of DetailsGridRowModel. When I disable the row and column virtualization everything works fine.
- The grid starts to re-bind data to a control that is no-longer visible and hence might be re-used.
- The data that gets picked up for binding is not in the correct order. So the order of items gets lost on sort and that causes a lot of problems and confusion.
Let me illustrate. Say the number of rows visible is 5 and the data for each row is the following list. Lets also assume that the == bars represent the top and bottom edges of the grid control.
let's say my list is containing the following data
- a
- b
- c
- d
- e
- f
- g
- h
- i
- j
This is what the user sees then the grid first renders.
==================
- a
- b
- c
- d
- e
==================
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
Now lets assume that the user scolls to the bottom. The user sees the following.
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
===================
- f
- g
- h
- i
- j
However now when the user scrolls up, the grid does not pick up the items in the list in the correct order. So this is what the user might see (I say might since what gets picked up and bound doesn't seem to be deterministic.)
==================
- g
- i
- a
- b
- d
==================
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
If you notice in the illustration above, I have tried to show that the list shown to the user is not fixed at all. It actually changes and depends on various things which change the timing of the the events firing inside such as
- The user stop scrolling and removed the mouse from the scrollbar when he reached at the bottom (as in mousebuttonup event fired or not) and then scrolled up again.
- OR The user scrolled to the bottom and with mouse button still down scrolled to the top slowly or very quickly, etc.
In fact sometimes if the user now scrolls down this is what he might see which absolutly confuses the user.
- ? <can't see this right now>
- ? <can't see this right now>
- ? <can't see this right now>
==================
- b
- d
- a
- c
- f
==================
- ? <can't see this right now>
- ? <can't see this right now>
In the real solution I have about 60 rows and 30 are visible on the grid at any time.
Binding to the properties was done only in XAML (xaml binding and using converters). Code did not relied on binding the properties to different parts of the control.
Hi,
I'm currently using version 2010.3.1314.1040. Our gridview typically contains over 1000 rows. One column uses a data template that has a user control, which data binds to a view model.
With virtualization enabled, we see the behavior described in this thead. The cell value bound changes as you vertically scroll the cell into and out of view. As a former poster describes, the value picked up for binding seems to be re-used or in the wrong order.
I've also tried on the 2011.1.419 relase, but see the same behavior.
Please advise.
Can you post an example where we can reproduce this with our latest official version - Q1 2011 SP1?
All the best,Vlad
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!
Here is a link to our project files: http://techsupportfromcal.com/VirtualizationScrollingProblem/VirtualizationScrollingProblem.zip
This is a matter of considerable urgency for us. Thanks for your assistance.
Quoting from the ReadMe file in our test application:
* This test application illustrates a problem which we are experiencing with our Telerik Silverlight GridView. * The GridView has three columns which display images. The first image column contains a standard Silverlight * Image Control. The second column contains a Silverlight User Control which in turn contains a Silverlight * Image Control. The third column shows a Silverlight Image Control hosted in a Silverlight Custom Control. * * As can be seen from running this application, the first two columns display the correct images when * scrolling but the third column does not. As you scroll, the images in the third column come from * other rows as the Telerik virtualization process reuses some grid components to improve performance. * If you set the EnableRowVirtualization property to False, this problem goes away. However, our data * sets are often very large and setting this property to False results in an unacceptable degradation * in performance. * * The third image column also contains a textblock which displays the Identifier Name. As can be * seen, this value is correct even though the wrong image is usually displayed. * * We have tried both the User Control and Custom Control approaches in our application and both * exhibit this scrolling problem. Of course, our actual controls are much more complex than this * sample application. * * This problem did not occur with the initial release of the Telerik controls from 2010 Q3. * We first noticed this problem after applying SP1 to the Q3 release. This test application * as requested by Telerik support uses the Q1 2011 release.
Thanks.
We've checked your scenario with the standard Microsoft Silverlight DataGrid and the behavior is exactly the same. It seems that the problem is in your BasicStructure component - please verify this!
Best wishes,Vlad
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!
1. Our application uses the Telerik Grid Control, not the Microsoft Grid Control and at least as of this point we are not looking to switch.
2. I would be happy to review any suggestions which you have regarding a possible problem with the BasicStructure component in my test application. However, for purpose of creating this test application I made this component as simple as possible (our actual application is much more complicated). It consists of nothing more than a custom control with two dependency properties and a UI consisting of a textblock and an image control. The textblock refreshes correctly but the image control does not. I don't mind at all removing the textblock since we don't actually have one of those in our real application but I can't remove the image control because that is the whole point of this column in our application.
3. This test application works just fine with your Q3 2010 controls (pre SP1). Here's a link:
http://techsupportfromcal.com/VirtualizationScrollingProblem/VirtualizationScrollingProblemQ32010.zip
If this test application works just fine with an earlier version of your controls but is broken with the current version of your controls, I would conclude that you must have changed something in how your controls work. That is what we would like you to check into.
4. In our actual application we have two columns which are causing this problem -- one with an image and the other with a list box. It didn't seem necessary to illustrate both problems since a fix for one of them will most likely provide a solution for both of them. We have tested many different variations of these controls in our application (both Silverlight UserControls and Silverlight Custom Controls) and they all have this same problem.
Here is how to change your custom control + converter to fix this:
<
Style
TargetType
=
"CustomControls:BasicStructure"
>
<
Setter
Property
=
"Background"
Value
=
"White"
/>
<
Setter
Property
=
"Template"
>
<
Setter.Value
>
<
ControlTemplate
TargetType
=
"CustomControls:BasicStructure"
>
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"{TemplateBinding Background}"
>
<
StackPanel
Orientation
=
"Vertical"
>
<
TextBlock
x:Name
=
"txbImageName"
Text
=
"{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ImageName}"
/>
<
Image
x:Name
=
"StructureImage"
Source="{Binding RelativeSource={RelativeSource TemplatedParent},
Path
=
ImageName
, Converter={StaticResource imageNameToImageConverter}}"
Height
=
"100"
Width
=
"100"
/>
</
StackPanel
>
</
Grid
>
</
ControlTemplate
>
</
Setter.Value
>
</
Setter
>
</
Style
>
public
class
BasicStructureToImageConverter :IValueConverter
{
public
object
Convert(
object
value, Type targetType,
object
parameter, System.Globalization.CultureInfo culture)
{
string
imageName = value
as
string
;
Uri uri =
new
Uri(@
"http://localhost:6449"
+
"/images/"
+ HttpUtility.UrlEncode(imageName) +
".png"
, UriKind.Absolute);
return
new
BitmapImage(uri);
}
public
object
ConvertBack(
object
value, Type targetType,
object
parameter, System.Globalization.CultureInfo culture)
{
throw
new
NotImplementedException();
}
}
Vlad
the Telerik team
Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!
I guess that one of the disadvantages of simplifying our test application to remove most of the complexities of our real application is that some of the constraints of our application are no longer clear. Your proposed solution would work nicely in our case if we needed only a simple string in our value converter. In our actual application, however, we need four items of data inside the value converter:
1. a string which via some business logic is converted into the name of the file for our image,
2. a specification of which default image to use if there is no image corresponding to that file name,
3. the height and
4. the width of the desired image.
That is the reason why our real application and the test application built to simulate the real application, pass in an object which can include each of those four values as properties.
Thanks.
Sample application generates some data with selected checkbox in first column.
Run application. Deselect checkbox in first row. Than scroll down using keyboard. Note selection bar in some rows and wrongly deselected checkboxes.
XAML:
<
UserControl
x:Class
=
"GridViewCellTemplateBug.MainPage"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable
=
"d"
d:DesignHeight
=
"300"
d:DesignWidth
=
"400"
>
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"White"
>
<
telerik:RadGridView
x:Name
=
"rgvProducts"
Grid.Row
=
"1"
Margin
=
"0,10,0,5"
CanUserFreezeColumns
=
"False"
GridLinesVisibility
=
"Both"
HorizontalAlignment
=
"Stretch"
VerticalAlignment
=
"Stretch"
FontSize
=
"10"
FontWeight
=
"Normal"
Height
=
"Auto"
ShowGroupPanel
=
"False"
IsFilteringAllowed
=
"True"
AutoGenerateColumns
=
"False"
IsReadOnly
=
"False"
CanUserSelect
=
"False"
>
<
telerik:RadGridView.Columns
>
<
telerik:GridViewDataColumn
Header
=
"Select"
>
<
telerik:GridViewDataColumn.CellTemplate
>
<
DataTemplate
>
<
CheckBox
IsChecked
=
"{Binding Selected}"
IsEnabled
=
"True"
HorizontalAlignment
=
"Center"
/>
</
DataTemplate
>
</
telerik:GridViewDataColumn.CellTemplate
>
</
telerik:GridViewDataColumn
>
<
telerik:GridViewDataColumn
Header
=
"Description"
UniqueName
=
"SKUDescription"
IsReadOnly
=
"True"
/>
</
telerik:RadGridView.Columns
>
</
telerik:RadGridView
>
</
Grid
>
</
UserControl
>
Code:
using
System.Collections.Generic;
using
System.Windows.Controls;
using
System.ComponentModel;
namespace
GridViewCellTemplateBug
{
public
partial
class
MainPage : UserControl
{
public
MainPage()
{
InitializeComponent();
ProductCollection itemList =
new
ProductCollection();
for
(
int
i = 0; i < 100; i++)
{
Product item =
new
Product();
item.Selected =
true
;
item.SKUDescription =
"Description"
+ i.ToString() +
" number"
+ i.ToString() + i.ToString();
itemList.Add(item);
}
rgvProducts.ItemsSource = itemList;
}
}
public
class
Product :
object
, INotifyPropertyChanged
{
private
bool
_Selected;
public
string
SKUDescription {
get
;
set
; }
public
bool
Selected
{
get
{
return
_Selected; }
set
{
_Selected = value;
NotifyPropertyChanged(
"Selected"
);
}
}
public
event
PropertyChangedEventHandler PropertyChanged;
public
void
NotifyPropertyChanged(
string
propertyName)
{
if
(PropertyChanged !=
null
)
{
PropertyChanged(
this
,
new
PropertyChangedEventArgs(propertyName));
}
}
}
public
class
ProductCollection : List<Product>
{
public
ProductCollection() :
base
() { }
public
ProductCollection(Product[] items)
:
base
()
{
if
(items !=
null
)
{
foreach
(Product item
in
items)
{
this
.Add(item);
}
}
}
};
}
public
class
VirtualizedRadioButtonBehavior : Behavior<RadioButton>
{
protected
override
void
OnAttached()
{
AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
base
.OnAttached();
}
protected
override
void
OnDetaching()
{
AssociatedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
base
.OnDetaching();
}
void
AssociatedObject_LayoutUpdated(
object
sender, EventArgs e)
{
BindingExpression binding = AssociatedObject.GetBindingExpression(RadioButton.IsCheckedProperty);
if
(
null
!= binding)
{
binding.UpdateSource();
}
}
}
XAML:
<
RadioButton
IsChecked
=
"{Binding Value}"
Command
=
"{Binding ChangeValueCommand}"
> <
i:Interaction.Behaviors
>
<
behaviors:VirtualizedRadioButtonBehavior
/>
</
i:Interaction.Behaviors
>
</
RadioButton
>
I also tried a version where, instead of evaluating the binding, I had a property to compare the bound value to the actual IsChecked value:
public
class
VirtualizedRadioButtonBehavior : Behavior<RadioButton>
{
public
DependencyProperty SynchronizedPropertyProperty = DependencyProperty.Register(
"SynchronizedProperty"
,
typeof
(
bool
?),
typeof
(VirtualizedRadioButtonBehavior),
new
PropertyMetadata(
null
));
public
bool
? SynchronizedProperty
{
get
{
return
(
bool
?)GetValue(SynchronizedPropertyProperty); }
set
{ SetValue(SynchronizedPropertyProperty, value); }
}
protected
override
void
OnAttached()
{
AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
base
.OnAttached();
}
protected
override
void
OnDetaching()
{
AssociatedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
base
.OnDetaching();
}
void
AssociatedObject_LayoutUpdated(
object
sender, EventArgs e)
{
if
(SynchronizedProperty != AssociatedObject.IsChecked)
{
AssociatedObject.IsChecked = SynchronizedProperty;
}
}
}
I am not sure if it's any faster, but I settled for refreshing the binding, because the usage was simpler.
Hi Telerik,
A customer of ours is having this issue with the grid. When the grid first displays all is well. When they scroll down and then scroll back up to the top, the text in one of the columns changes to different values. Unfortunately it is something that we have been unable to replicate in house.
Reviewing our xaml, we note that the GridViewDataColumn columns that are teh problematic are ones where we have a custom CellTemplate defined.
Researching your forum I came across this link: http://www.telerik.com/forums/difference-between-cellstyle-template-and-celltemplate
I have now reworked the xaml to use CellStyle instead of CellTemplate.
In house everything works as is and I am hopeful to supply this change to our customer to have them try it.
In trying to understand if this will help and if so why I used JustDecompile on the Telerik.Windows.Control.GridView.dll and note that in Telerik.Windows.Control.GridView.DataCellsPresenter.SyncProperties() method there is a NotifyPropertyChanged call for CellStyle only. there is no call for CellTemplate.
Should Telerik also have a NotifyPropertyChanged call to CellTemplate in ​this SyncProperties() method and until it is added should we use CellStyle in our Xaml to assure everything stays synced when Row Virtualization is used?
- Tim
​
Would you please share how have you defined the hyperlink columns? Generally such issues may be observed when working with the visual elements (i.e. GridViewCell). You can also refer to the documentation on Styling or content mixed-up on scrolling.
A way to diagnose if this is the reason would be to disable RadGridView's UI virtualization. Please take a look at this article for a reference on UI Virtualization.
How does Hyperlink Column or Dynamic Hyperlink Column work for you?
Regards,
Dimitrina
Telerik