PDA

View Full Version : [CLOSED] Buffered Grid Scrolling repeats rows



jwhitmire36
Feb 06, 2013, 8:06 PM
Hello,
I have a buffered grid with both remote sort and filter that I'm getting a strange behavior when scrolling down the grid that I'll try to explain clearly, I'm including an example that shows the behavior. In the example PageSize is set to 100 and when I start scrolling down the grid when I get to about row #125 it seems to lose it's place and the data in the row starts repeating rows from the beginning of the grid, but the row number keeps incrementing normally. If you keep scrolling the next approx. 125 rows it will happen again. Changing the PageSize changes when it happens, so if I set PageSize to 150, it will start repeating around row #175. I've tried playing with other properties like the Buffer Zones but I can't seem to pinpoint what I'm doing wrong. I'm using version 2.1.1 in VS2010 w/.NET 4.0, see it in both IE8 and Chrome. Thanks in advance.

JW



<%@ Page Language="C#"%>
<%@ Register Assembly="Ext.NET" Namespace="Ext.Net" TagPrefix="ext" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
this.Store1.DataSource = this.dynData;
}
}
private List<object> dynData
{
get
{
List<object> comps = new List<object> { };

for (int i = 0; i < 500; i++)
{
comps.Add(new {company = "Company " + i, price = 71.72, change = 0.02, pctChange = 0.03, lastCahnge = new DateTime(2013, 9, 1) });
}

return comps;
}
}
protected void Store1_RefreshData(object sender, StoreReadDataEventArgs e)
{
List<object> data = this.dynData;
string s = e.Parameters[this.GridFilters1.ParamPrefix];
//-- start filtering ------------------------------------------------------------
if (!string.IsNullOrEmpty(s))
{
FilterConditions fc = new FilterConditions(s);

foreach (FilterCondition condition in fc.Conditions)
{
Comparison comparison = condition.Comparison;
string field = condition.Field;
FilterType type = condition.Type;

object value;
switch (condition.Type)
{
case FilterType.Boolean:
value = condition.Value<bool>();
break;
case FilterType.Date:
value = condition.Value<DateTime>();
break;
case FilterType.List:
value = condition.List;
break;
case FilterType.Numeric:
if (data.Count > 0 && data[0].GetType().GetProperty(field).PropertyType == typeof(int))
{
value = condition.Value<int>();
}
else
{
value = condition.Value<double>();
}

break;
case FilterType.String:
value = condition.Value<string>();
break;
default:
throw new ArgumentOutOfRangeException();
}

data.RemoveAll(
item =>
{
object oValue = item.GetType().GetProperty(field).GetValue(item, null);
IComparable cItem = oValue as IComparable;

switch (comparison)
{
case Comparison.Eq:

switch (type)
{
case FilterType.List:
return !(value as List<string>).Contains(oValue.ToString());
case FilterType.String:
return !oValue.ToString().StartsWith(value.ToString());
default:
return !cItem.Equals(value);
}

case Comparison.Gt:
return cItem.CompareTo(value) < 1;
case Comparison.Lt:
return cItem.CompareTo(value) > -1;
default:
throw new ArgumentOutOfRangeException();
}
}
);
}
}
//-- end filtering ------------------------------------------------------------
//-- start sorting ------------------------------------------------------------
if (e.Sort.Length > 0)
{
data.Sort(delegate(object x, object y)
{
object a;
object b;

int direction = e.Sort[0].Direction == Ext.Net.SortDirection.DESC ? -1 : 1;

a = x.GetType().GetProperty(e.Sort[0].Property).GetValue(x, null);
b = y.GetType().GetProperty(e.Sort[0].Property).GetValue(y, null);
return CaseInsensitiveComparer.Default.Compare(a, b) * direction;
});
}
//-- end sorting ------------------------------------------------------------
this.GridPanel1.GetStore().DataSource = data;
}
protected void Button1_Click(object sender, DirectEventArgs e)
{
RowSelectionModel selRows = GridPanel1.GetSelectionModel() as RowSelectionModel;
this.Store1.DataSource = this.dynData;
selRows.ClearSelection();
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<script type="text/javascript">
var template = '<span style="color:{0};">{1}</span>';
var change = function (value) {
return Ext.String.format(template, (value > 0) ? "green" : "red", value);
};
var pctChange = function (value) {
return Ext.String.format(template, (value > 0) ? "green" : "red", value + "%");
};
</script>
</head>
<body>
<form id="form1" runat="server">
<ext:ResourceManager ID="ExtResourceManager" runat="server" DisableViewState="false" RenderStyles="Embedded"></ext:ResourceManager>
<ext:GridPanel ID="GridPanel1" runat="server" Title="Sample Grid" Width="650" Height="350" EnableColumnMove="false">
<Store>
<ext:Store ID="Store1" runat="server" Buffered="true" PageSize="100" RemoteSort="true"
RemoteFilter="true" OnReadData="Store1_RefreshData" LeadingBufferZone="50" TrailingBufferZone="50">
<Proxy>
<ext:PageProxy/>
</Proxy>
<Model>
<ext:Model ID="Model1" runat="server">
<Fields>
<ext:ModelField Name="company" />
<ext:ModelField Name="price" Type="Float" />
<ext:ModelField Name="change" Type="Float" />
<ext:ModelField Name="pctChange" Type="Float" />
<ext:ModelField Name="lastChange" Type="Date" DateFormat="M/d hh:mmtt" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<ColumnModel OverflowY="Auto">
<Columns>
<ext:RowNumbererColumn Width="50"></ext:RowNumbererColumn>
<ext:Column ID="Column1" runat="server" Text="Company" DataIndex="company" Flex="1" />
<ext:Column ID="Column2" runat="server" Text="Price" DataIndex="price">
<Renderer Format="UsMoney" />
</ext:Column>
<ext:Column ID="Column3" runat="server" Text="Change" DataIndex="change">
<Renderer Fn="change" />
</ext:Column>
<ext:Column ID="Column4" runat="server" Text="Change" DataIndex="pctChange">
<Renderer Fn="pctChange" />
</ext:Column>
<ext:DateColumn ID="DateColumn1" runat="server" Text="Last Updated" DataIndex="lastChange" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:CheckboxSelectionModel ID="CheckboxSelectionModel1" runat="server" Mode="Single" AllowDeselect="true" ShowHeaderCheckbox="false"></ext:CheckboxSelectionModel>
</SelectionModel>
<Features>
<ext:GridFilters ID="GridFilters1" runat="server" Local="false" Enabled="true">
<Filters>
<ext:StringFilter DataIndex="company"></ext:StringFilter>
</Filters>
</ext:GridFilters>
</Features>
</ext:GridPanel>
</form>
</body>
</html>

Baidaly
Feb 07, 2013, 12:17 AM
Hello!

Try to set the following:



<ext:Store ID="Store1" runat="server" Buffered="true" PageSize="500" RemoteSort="true"
RemoteFilter="true" OnReadData="Store1_RefreshData">
...
</ext:Store>

jwhitmire36
Feb 07, 2013, 3:32 PM
Hello!

Try to set the following:



<ext:Store ID="Store1" runat="server" Buffered="true" PageSize="500" RemoteSort="true"
RemoteFilter="true" OnReadData="Store1_RefreshData">
...
</ext:Store>


Hi Baidaly,
Setting that PageSize works only for this test example I created where I'm specifically setting the #rows to 500, you're basically turning off buffering. In my actual application the number of rows is dynamic and could have serveral thousand rows and I want to buffer the grid for perfomance purposes. If I set Buffered=false it works fine as well, so there's something going on when it's buffered and the grid goes to load the next page it's not keeping it's place on the datasource?

JW

Vladimir
Feb 07, 2013, 4:10 PM
I tested your sample with latest code (from SVN trunk) and I cannot reproduce such behaviour. Can you update from SVN trunk and retest?

jwhitmire36
Feb 07, 2013, 6:30 PM
Hi Vladimir,
I downloaded the current source and now my example page works. I did however notice that if I remove the Leading and Trailing BufferZone settings from the Store it still happens. I'm attaching a screen shot of what I see.

JW

Vladimir
Feb 07, 2013, 7:09 PM
Trunk works with ExtJS 4.2 beta 2 version
In this version I suggest to use BufferedRenderer plugin for GridPanel (remove Buffered (and related) options from the store and add that plugin to the grid)



<%@ Page Language="C#"%>
<%@ Register Assembly="Ext.NET" Namespace="Ext.Net" TagPrefix="ext" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!X.IsAjaxRequest)
{
this.Store1.DataSource = this.dynData;
}
}
private List<object> dynData
{
get
{
List<object> comps = new List<object> { };

for (int i = 0; i < 500; i++)
{
comps.Add(new {company = "Company " + i, price = 71.72, change = 0.02, pctChange = 0.03, lastCahnge = new DateTime(2013, 9, 1) });
}

return comps;
}
}
protected void Store1_RefreshData(object sender, StoreReadDataEventArgs e)
{
List<object> data = this.dynData;
string s = e.Parameters[this.GridFilters1.ParamPrefix];
//-- start filtering ------------------------------------------------------------
if (!string.IsNullOrEmpty(s))
{
FilterConditions fc = new FilterConditions(s);

foreach (FilterCondition condition in fc.Conditions)
{
Comparison comparison = condition.Comparison;
string field = condition.Field;
FilterType type = condition.Type;

object value;
switch (condition.Type)
{
case FilterType.Boolean:
value = condition.Value<bool>();
break;
case FilterType.Date:
value = condition.Value<DateTime>();
break;
case FilterType.List:
value = condition.List;
break;
case FilterType.Numeric:
if (data.Count > 0 && data[0].GetType().GetProperty(field).PropertyType == typeof(int))
{
value = condition.Value<int>();
}
else
{
value = condition.Value<double>();
}

break;
case FilterType.String:
value = condition.Value<string>();
break;
default:
throw new ArgumentOutOfRangeException();
}

data.RemoveAll(
item =>
{
object oValue = item.GetType().GetProperty(field).GetValue(item, null);
IComparable cItem = oValue as IComparable;

switch (comparison)
{
case Comparison.Eq:

switch (type)
{
case FilterType.List:
return !(value as List<string>).Contains(oValue.ToString());
case FilterType.String:
return !oValue.ToString().StartsWith(value.ToString());
default:
return !cItem.Equals(value);
}

case Comparison.Gt:
return cItem.CompareTo(value) < 1;
case Comparison.Lt:
return cItem.CompareTo(value) > -1;
default:
throw new ArgumentOutOfRangeException();
}
}
);
}
}
//-- end filtering ------------------------------------------------------------
//-- start sorting ------------------------------------------------------------
if (e.Sort.Length > 0)
{
data.Sort(delegate(object x, object y)
{
object a;
object b;

int direction = e.Sort[0].Direction == Ext.Net.SortDirection.DESC ? -1 : 1;

a = x.GetType().GetProperty(e.Sort[0].Property).GetValue(x, null);
b = y.GetType().GetProperty(e.Sort[0].Property).GetValue(y, null);
return CaseInsensitiveComparer.Default.Compare(a, b) * direction;
});
}
//-- end sorting ------------------------------------------------------------
this.GridPanel1.GetStore().DataSource = data;
}
protected void Button1_Click(object sender, DirectEventArgs e)
{
RowSelectionModel selRows = GridPanel1.GetSelectionModel() as RowSelectionModel;
this.Store1.DataSource = this.dynData;
selRows.ClearSelection();
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<script type="text/javascript">
var template = '<span style="color:{0};">{1}</span>';
var change = function (value) {
return Ext.String.format(template, (value > 0) ? "green" : "red", value);
};
var pctChange = function (value) {
return Ext.String.format(template, (value > 0) ? "green" : "red", value + "%");
};
</script>
</head>
<body>
<form id="form1" runat="server">
<ext:ResourceManager ID="ExtResourceManager" runat="server" DisableViewState="false" RenderStyles="Embedded"></ext:ResourceManager>
<ext:GridPanel ID="GridPanel1" runat="server" Title="Sample Grid" Width="650" Height="350" EnableColumnMove="false">
<Store>
<ext:Store ID="Store1" runat="server" RemoteSort="true"
RemoteFilter="true" OnReadData="Store1_RefreshData">
<Proxy>
<ext:PageProxy/>
</Proxy>
<Model>
<ext:Model ID="Model1" runat="server">
<Fields>
<ext:ModelField Name="company" />
<ext:ModelField Name="price" Type="Float" />
<ext:ModelField Name="change" Type="Float" />
<ext:ModelField Name="pctChange" Type="Float" />
<ext:ModelField Name="lastChange" Type="Date" DateFormat="M/d hh:mmtt" />
</Fields>
</ext:Model>
</Model>
</ext:Store>
</Store>
<Plugins>
<ext:BufferedRenderer runat="server" />
</Plugins>
<ColumnModel OverflowY="Auto">
<Columns>
<ext:RowNumbererColumn Width="50"></ext:RowNumbererColumn>
<ext:Column ID="Column1" runat="server" Text="Company" DataIndex="company" Flex="1" />
<ext:Column ID="Column2" runat="server" Text="Price" DataIndex="price">
<Renderer Format="UsMoney" />
</ext:Column>
<ext:Column ID="Column3" runat="server" Text="Change" DataIndex="change">
<Renderer Fn="change" />
</ext:Column>
<ext:Column ID="Column4" runat="server" Text="Change" DataIndex="pctChange">
<Renderer Fn="pctChange" />
</ext:Column>
<ext:DateColumn ID="DateColumn1" runat="server" Text="Last Updated" DataIndex="lastChange" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:CheckboxSelectionModel ID="CheckboxSelectionModel1" runat="server" Mode="Single" AllowDeselect="true" ShowHeaderCheckbox="false"></ext:CheckboxSelectionModel>
</SelectionModel>
<Features>
<ext:GridFilters ID="GridFilters1" runat="server" Local="false" Enabled="true">
<Filters>
<ext:StringFilter DataIndex="company"></ext:StringFilter>
</Filters>
</ext:GridFilters>
</Features>
</ext:GridPanel>
</form>
</body>
</html>

jwhitmire36
Feb 07, 2013, 9:19 PM
Thanks Validmir, seems to work in my example good. I'll update my application and if I have any other problems will post back.

So it sounds like the Buffered Store is a bug with Sencha version?

JW

Daniil
Feb 08, 2013, 5:39 AM
Hi,

I don't think it is a bug. You set up PageSize="100", but doesn't take it into account in the OnReadData handler. You returns 500 records each request, but the Store expects 100.

Setting up PageSize="500" as @Baidaly suggested appears to fix the problem with your initial example. If PageSize doesn't equal the amount of records you should return the records from the OnReadData handler just only for the requested page. There are the Start, Limit and Page parameters for that in the StoreReadDataEventArgs instance.

jwhitmire36
Feb 08, 2013, 10:40 PM
I seem to be good with buffering, but now that I updated my actual application with the SVN source code(4793), Tooltip and EmptyText are no longer working. I verified that they still work with my earlier version of the source. I did just notice that Rev 4798 is now been uploaded since yesterday, I will have to try that out next week before posting a new thread.

JW

Baidaly
Feb 08, 2013, 11:09 PM
Unfortunately, version of Ext JS in trunk still is beta and if you will provide sample to reproduce we can send them to Sencha and give temp fix

Daniil
Feb 09, 2013, 6:49 AM
Yes, separate threads for each issue - ToolTip and EmptyText - with test cases to reproduce would be greatly appreciated.