public class GridApp
{
public static void Start()
{
HtmlElement gridOuter = HtmlDocument.Current.GetElementById("grid");
Grid grid = CreateGrid(gridOuter);
grid.DataSource = CreateDataSource(0, 100000000000);
grid.Body.RowHeight = 24;
ResizeMainElement(gridOuter);
AdviseContextMenus(grid);
}
internal static Grid<long?> CreateGrid(HtmlElement gridOuter)
{
Grid<long?> grid = new Grid<long?>() { Element = gridOuter };
InitGrid(grid);
return grid;
}
internal static void InitGrid(Grid<long?> grid)
{
grid.SortColumns.SortMode = GridSortMode.MultipleColumn;
GridFilter gridFilter = new GridFilter(grid, Dummies.Action);
for (int i = 0; i < 100; i++)
{
GridColumn<long> column;
switch (i % 7)
{
case 0:
column = new TextColumn<long>()
{
Accessor = delegate(long data)
{
return ((char)((int)'a' + (data % 26))).ToString() + data;
}
};
gridFilter.AddFilter(column, new TextFilterEditor());
break;
case 1:
column = new JDateColumn<long>()
{
Accessor = delegate(long data) { return new JDate(2000, 0, 1).AddMinutes(data % 100000); },
Format = "{0:yyyy-MM-dd HH:mm}",
ClassName = GridSkin.Instance.RightAlignGridClass
};
gridFilter.AddFilter(column, new RangeFilterEditor<JDate>(new JDateRangeEditor()));
break;
case 2:
column = new LongColumn<long>()
{
Accessor = delegate(long data) { return data; },
Format = "{0:N0}",
ClassName = GridSkin.Instance.RightAlignGridClass
};
gridFilter.AddFilter(column, new RangeFilterEditor<long?>(new NumericRangeEditor<long?>()));
break;
case 3:
column = new IntColumn<long>()
{
Accessor = delegate(long data) { return (int)(data % 1000); },
ClassName = GridSkin.Instance.RightAlignGridClass
};
gridFilter.AddFilter(column, new RangeFilterEditor<int?>(new NumericRangeEditor<int?>()));
break;
case 4:
column = new DoubleColumn<long>()
{
Accessor = delegate(long data) { return (double)data / 100; },
Format = "{0:N2}",
ClassName = GridSkin.Instance.RightAlignGridClass
};
gridFilter.AddFilter(column, new RangeFilterEditor<double?>(new NumericRangeEditor<double?>()));
break;
case 5:
column = new IntColumn<long>()
{
Accessor = delegate(long data) { return (int)(data % 1000); },
ClassName = GridSkin.Instance.RightAlignGridClass
};
gridFilter.AddFilter(column, new ListFilterEditor<Node>(new ListBox<Node>()
{
DataSource = new NodeSource(1, 1000),
Renderer = TreeViewApp.Render
}));
break;
default:
column = new GridColumn<long>()
{
Renderer = MultiRenderer.Render<long>(new Renderer(i).Renderers)
};
break;
}
column.Width = 100;
column.AllowResize = ((i % 7) != 0);
column.SortMode = ((i % 3) != 0) ? GridColumnSortMode.Allow : GridColumnSortMode.NotAllow;
column.Header = new RightFilterColumnHeader()
{
Content = new SortableTextColumnHeader()
{
Text = (column.AllowResize ? "CanResize " : "")
+ (column.SortMode != GridColumnSortMode.NotAllow ? "CanSort " : "") + i
}
};
;
grid.Columns.Add(column);
}
grid.Header.Height = 24;
grid.FixedLeftColumns = 2;
grid.GridClassName = "grid";
grid.RowsSelection.AllowMultipleRowSelection = true;
grid.FilterColumns.AllowFilter = true;
AdviseDragDrop(grid);
}
internal static void AdviseDragDrop(Grid<long?> grid)
{
grid.Body.AdviseDrag(delegate(HtmlMouseEvent e)
{
GridBodyHit hit = grid.Body.Hit(e);
return new GridDragSource((((GridRowsSelection)grid.RowsSelection).Contains(hit.Row) ? grid.RowsSelection : grid.DataSource[hit.Row]), DropEffects.All);
});
grid.Body.AdviseDrop(delegate(object dataObject)
{
ILongReadonlyCollection<long?> source = dataObject as ILongReadonlyCollection<long?>;
if (source == null && dataObject is long)
{
source = new LongReadonlyCollection<long?>(new long?[] { (long)dataObject });
}
if (source != null && source.Count != 0)
{
long? first = null;
source.Enumerate(0,
delegate(long? o)
{
first = o;
return false;
});
if (first != null)
{
return new GridDropTarget(grid);
}
}
return null;
});
if (SupportedHtml5Features.File)
{
GridRowDropTarget dropTarget = new GridRowDropTarget(grid);
grid.Body.AdviseDrop(
delegate (HtmlMouseEvent e)
{
dropTarget.DragOver(e);
dropTarget.ShowFeedback();
},
delegate (HtmlDropEvent e)
{
dropTarget.Drop(e);
MessageBox.Show(string.Format("Drop {0} files", e.Files.Length));
});
HtmlDocument.Current.Body.AdviseDrop(null, null);
}
}
internal static void AdviseContextMenus(Grid grid)
{
grid.Header.AdviseContextMenu(delegate(int columnIndex)
{
return new ContextMenu()
{
Skin = MenuApp.Menu.Value.Skin,
List = MenuApp.Menu.Value.List,
Renderer = MenuApp.Menu.Value.Renderer,
Execute = delegate(IHierarchyLevel menuLevel, long menuItemIndex)
{
HtmlWindow.Current.Alert("Menu: " + MenuApp.Text(menuLevel, menuItemIndex) + " Column: " + columnIndex);
}
};
});
grid.Body.AdviseContextMenu(delegate(long rowIndex, int columnIndex)
{
return new ContextMenu()
{
Skin = MenuApp.Menu.Value.Skin,
List = MenuApp.Menu.Value.List,
Renderer = MenuApp.Menu.Value.Renderer,
Execute = delegate(IHierarchyLevel menuLevel, long menuItemIndex)
{
HtmlWindow.Current.Alert("Menu: " + MenuApp.Text(menuLevel, menuItemIndex)
+ " Row: " + rowIndex
+ " Column: " + columnIndex);
}
};
});
}
internal static DataSource CreateDataSource(long start, long count) { return new DataSource(start, count); }
internal static void ResizeMainElement(HtmlElement elem)
{
new ResizeObserver(delegate() { Resize(elem); }).Notify();
}
static void Resize(HtmlElement elem)
{
HtmlRect rc = elem.GetBoundingClientRect();
int height = HtmlWindow.Current.InnerHeight - rc.Top - elem.OffsetHeight + elem.ClientHeight - 70;
if (height < 40)
{
height = 40;
}
int width = HtmlWindow.Current.InnerWidth - rc.Left - elem.OffsetWidth + elem.ClientWidth;
if (width < 40)
{
width = 40;
}
elem.Style.Width = width + "px";
elem.Style.Height = height + "px";
}
internal class Renderer
{
readonly static object errorImageState = new object();
readonly int index;
readonly Func<HtmlElement, long, object, object>[] errorRenderers;
readonly Func<HtmlElement, long, object, object>[] textRenderers;
internal Renderer(int index)
{
this.index = index;
errorRenderers = new Func<HtmlElement, long, object, object>[] { RenderImage, RenderErrorText };
textRenderers = new Func<HtmlElement, long, object, object>[] { RenderText };
}
object RenderImage(HtmlElement outer, long value, object state)
{
if (state != errorImageState)
{
outer.ClassName = "gridErrorImage";
outer.Title = "Sample error info";
outer.InnerHtml = " ";
}
return errorImageState;
}
object RenderErrorText(HtmlElement outer, long value, object state)
{
ErrorTextState tstate = State.Ensure<ErrorTextState>(state);
if (tstate.Col < 0)
{
outer.ClassName = "gridErrorText";
}
if (tstate.Col != index || tstate.Value != value)
{
tstate.Col = index;
tstate.Value = value;
outer.InnerHtml = string.Format("{0}-{1}", value, index);
}
return tstate;
}
object RenderText(HtmlElement outer, long value, object state)
{
TextState tstate = State.Ensure<TextState>(state);
if (tstate.Col < 0)
{
outer.ClassName = "gridText";
}
if (tstate.Col != index || tstate.Value != value)
{
tstate.Col = index;
tstate.Value = value;
outer.InnerHtml = string.Format("{0}-{1}", value, index);
}
return tstate;
}
internal Func<HtmlElement, long, object, object>[] Renderers(long value)
{
return (value + index) % 5 == 0 ? errorRenderers : textRenderers;
}
}
class State
{
internal int Col;
internal long Value;
internal static TState Ensure<TState>(object state) where TState : State, new()
{
TState tState = state as TState;
if (tState == null)
{
tState = new TState();
tState.Col = -1;
}
return tState;
}
}
class ErrorTextState : State
{
}
class TextState : State
{
}
}
class DataSource : IObservableList
{
readonly long start;
readonly long count;
internal DataSource(long start, long count)
{
this.start = start;
this.count = count;
}
long IObservableList.Count
{
get { return count; }
}
internal long SearchIndex(long? key)
{
return key == null || key.Value < start || key.Value > start + count ? -1 : key.Value - start;
}
object IObservableList.this[long index]
{
get
{
CheckIndex(index);
return start + index;
}
}
IDisposable IObservable.Advise(Action observer)
{
return null;
}
IDisposable IObservableList.Advise(IListObserver observer)
{
return null;
}
void CheckIndex(long index)
{
(index >= 0 && index < count).Assert("Illegal index");
}
public override bool Equals(object obj)
{
DataSource other = obj as DataSource;
return other != null && start == other.start && count == other.count;
}
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" style="overflow:hidden;width:100%;height:100%">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
<meta http-equiv="x-ua-compatible" content="IE=11;IE=10;IE=9;IE=8;IE=7" />
<link rel="stylesheet" href="styles/jscriptsuite.css" type="text/css" />
<link rel="stylesheet" href="styles/summary.css" type="text/css" />
<script language="javascript" type="text/javascript" src="js/Grid.js"></script>
</head>
<body onload="StartScript()" scroll="no" style="overflow:hidden; margin-top:0 0 0 0;width:100%;height:100%">
Grid.html: Grid control. Implemented Grid/Column - resizing, virtual scrolling. Visualization of (multiple)column sorting and filtering.
(Multiple)Row selectecion mouse and keyboard. Context Menu Integration.
<div id="grid" class="gridOuter" style="overflow:hidden;width:100%"></div>
</body>
</html>