using C1.Web.Mvc;
using MultiRowExplorer.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using C1.Web.Mvc.Serialization;
namespace MultiRowExplorer.Controllers
{
public partial class MultiRowController : Controller
{
private static List<Sale> Source = Sale.GetData(10).ToList<Sale>();
public ActionResult CustomEditors()
{
ViewBag.Countries = Sale.GetCountries();
ViewBag.Products = Sale.GetProducts();
return View();
}
public ActionResult CustomEditors_Bind([C1JsonRequest] CollectionViewRequest<Sale> requestData)
{
return this.C1Json(CollectionViewHelper.Read(requestData, Source));
}
public ActionResult MultiRowEditorsUpdate([C1JsonRequest]CollectionViewEditRequest<Sale> requestData)
{
return this.C1Json(CollectionViewHelper.Edit<Sale>(requestData, sale =>
{
string error = string.Empty;
bool success = true;
var fSale = Source.Find(item => item.ID == sale.ID);
fSale.Country = sale.Country;
fSale.Amount = sale.Amount;
fSale.Start = sale.Start;
fSale.End = sale.End;
fSale.Product = sale.Product;
fSale.Active = sale.Active;
fSale.Amount2 = sale.Amount2;
fSale.Color = sale.Color;
return new CollectionViewItemResult<Sale>
{
Error = error,
Success = success && ModelState.IsValid,
Data = fSale
};
}, () => Source));
}
public ActionResult MultiRowEditorsCreate([C1JsonRequest]CollectionViewEditRequest<Sale> requestData)
{
return this.C1Json(CollectionViewHelper.Edit(requestData, item =>
{
string error = string.Empty;
bool success = true;
try
{
Source.Add(item);
item.ID = Source.Max(u => u.ID) + 1;
}
catch (Exception e)
{
error = e.Message;
success = false;
}
return new CollectionViewItemResult<Sale>
{
Error = error,
Success = success,
Data = item
};
}, () => Source));
}
public ActionResult MultiRowEditorsDelete([C1JsonRequest]CollectionViewEditRequest<Sale> requestData)
{
return this.C1Json(CollectionViewHelper.Edit(requestData, item =>
{
string error = string.Empty;
bool success = true;
try
{
var resultItem = Source.Find(u => u.ID == item.ID);
Source.Remove(resultItem);
}
catch (Exception e)
{
error = e.Message;
success = false;
}
return new CollectionViewItemResult<Sale>
{
Error = error,
Success = success,
Data = item
};
}, () => Source));
}
}
}
@model IEnumerable<Sale>
@{
List<string> countries = ViewBag.Countries;
List<string> products = ViewBag.Products;
}
@section Scripts{
<script type="text/javascript">
c1.documentReady(function () {
var grid = wijmo.Control.getControl('#customEditorsMultiRow');
grid.hostElement.addEventListener('keydown', function (e) {
if (e.keyCode == 32) {
e.preventDefault();
}
});
});
// The following scripts added for customizing the updating for the Product column.
// apply the customized updating for the Product column
function cellEditEnding(grid, cellRangeEventArgs) {
var row = cellRangeEventArgs.row, col = cellRangeEventArgs.col;
var bcol = grid.getBindingColumn(grid.cells, row, col);
// when it is the editor of the "Product" column,
// apply the updating manually.
if (!cellRangeEventArgs.cancel
&& cellRangeEventArgs.panel.cellType == wijmo.grid.CellType.Cell
&& bcol.binding == 'Product') {
updateCellValue(grid, cellRangeEventArgs);
cellRangeEventArgs.cancel = true;
}
}
function productEditorFocus(event) {
var input = event.currentTarget;
if (input) {
wijmo.setSelectionRange(input, 0, input.value.length);
}
}
function productEditorBlur(event) {
var input = event.currentTarget;
setTimeout(function () {
if (wijmo.contains(document.activeElement, input)
// ensure the input element is not removed from the page.
|| !document.body.contains(input)) {
return;
}
var wrapper = input.parentNode,
cellRange = getActiveEditorCellRange(input),
grid = wijmo.Control.getControl('#customEditorsMultiRow');
updateCellValue(grid, cellRange);
wrapper.parentNode.removeChild(wrapper);
});
}
// the id of the element would be [MultiRow's id] + "_Cell_r" + row + "_c" + col + "_"
function getActiveEditorCellRange(ele) {
var id = ele.id, strId,
row, col, index;
if (id) {
strId = id.substr('customEditorsMultiRow_Cell_r'.length);
index = strId.indexOf('_c');
row = parseInt(strId.substring(0, index));
col = parseInt(strId.substr(index + 2));
return { row: row, col: col };
}
}
// update the Product cell's value with its editor.
function updateCellValue(grid, cellRangeEventArgs) {
var row, col,
sel = grid.selection,
cv = grid.collectionView;
row = cellRangeEventArgs.row;
col = cellRangeEventArgs.col;
cv.editItem(cv.items[row]);
var input = getEditorControl(row, col);
grid.setCellData(row, col, input.value);
cv.commitEdit();
cv.commitNew();
grid.select(sel);
}
function getEditorControl(row, col) {
var elementId = 'customEditorsMultiRow_Cell_r' + row + '_c' + col;
return document.getElementById(elementId);
}
</script>
}
<!-- MultiRow hosting the custom editors -->
<c1-multi-row id="customEditorsMultiRow" allow-add-new="true" allow-delete="true"
key-action-tab="Cycle" class="multirow" cell-edit-ending="cellEditEnding">
<c1-items-source read-action-url="@Url.Action("CustomEditors_Bind")"
update-action-url="@Url.Action("MultiRowEditorsUpdate")"
create-action-url="@Url.Action("MultiRowEditorsCreate")"
delete-action-url="@Url.Action("MultiRowEditorsDelete")">
</c1-items-source>
<c1-multi-row-cell-group>
<c1-multi-row-cell binding="ID" header="ID" is-read-only="true"></c1-multi-row-cell>
<c1-multi-row-cell binding="Active" header="Active" is-read-only="false"></c1-multi-row-cell>
</c1-multi-row-cell-group>
<c1-multi-row-cell-group>
<c1-multi-row-cell binding="Start" header="Date" width="150" format="d">
<c1-flex-grid-cell-template is-editing="true">
<c1-input-date id="dateEditor" style="width:100%" is-required="false" format="d" template-bindings="@(new{ Value = "Start"})"></c1-input-date>
</c1-flex-grid-cell-template>
</c1-multi-row-cell>
<c1-multi-row-cell binding="End" header="Time" format="t">
<c1-flex-grid-cell-template is-editing="true">
<c1-input-time id="timeEditor" style="width:100%" is-required="false" step="30" format="t" template-bindings="@(new {Value="End"})"></c1-input-time>
</c1-flex-grid-cell-template>
</c1-multi-row-cell>
</c1-multi-row-cell-group>
<c1-multi-row-cell-group colspan="2">
<c1-multi-row-cell binding="Country" header="Country" colspan="2">
<c1-flex-grid-cell-template is-editing="true">
<c1-combo-box id="countryEditor" style="width:100%" is-editable="false" template-bindings="@(new {Text="Country"})">
<c1-items-source source-collection="@countries"></c1-items-source>
</c1-combo-box>
</c1-flex-grid-cell-template>
</c1-multi-row-cell>
<c1-multi-row-cell binding="Product" header="Product">
<c1-flex-grid-cell-template is-editing="true">
<input type="text" id="{{uid}}" onfocus="productEditorFocus(event)" onblur="productEditorBlur(event)" style="width:100%;height:100%" value="{{Product}}" />
</c1-flex-grid-cell-template>
</c1-multi-row-cell>
<c1-multi-row-cell binding="Color" header="Color">
<c1-flex-grid-cell-template is-editing="true">
<c1-input-color id="colorEditor" style="width:100%" is-required="false" template-bindings="@(new {Value="Color"})"></c1-input-color>
</c1-flex-grid-cell-template>
</c1-multi-row-cell>
</c1-multi-row-cell-group>
<c1-multi-row-cell-group>
<c1-multi-row-cell binding="Amount" header="Amount" format="n2">
<c1-flex-grid-cell-template is-editing="true">
<c1-input-number id="amountEditor" style="width:100%" is-required="false" format="c2" step="10" template-bindings="@(new {Value="Amount"})"></c1-input-number>
</c1-flex-grid-cell-template>
</c1-multi-row-cell>
<c1-multi-row-cell binding="Amount2" header="Amount2"></c1-multi-row-cell>
</c1-multi-row-cell-group>
</c1-multi-row>
@section Description{
<p>
This sample shows how you can use custom editors to change the values in <b>MultiRow</b> cells.
</p>
<p>
The sample uses the <b>EditTemplateId</b> property to specify the id of the template for cell editor.
When the user starts editing a cell, the editor will show and get the focus.
</p>
<p>
There are three kinds of editors.
</p>
<ul class="normal">
<li>
<b>Use C1 Input controls which has "Value" or "Text" property.</b>
<p>
You only need set the <b>EditTemplate</b> property of a cell.
</p>
<p>
If the grid allows adding a new row, you need set the editor's <b>IsRequired</b> to false.
If you want the editor full with the whole cell, you can set the style width to "100%".
</p>
<p>
In this sample, "Date", "Time", "Country", "Amount" and "Color" use C1 Input controls as the editors.
</p>
</li>
<li>
<b>Use other control or a C1 control which has NO "Value" or "Text" property.</b>
<p>
You need listen the grid's <b>OnClientCellEditEnding</b> event and set
<pre>
cellEditEndingEventArgs.cancel = true;
</pre>
to apply your updating.
</p>
<p>
Then you need consider when to update the cell value and remove the editor from a grid in your application.
For example, when the editor blurs, we need update the cell value and remove the editor.
</p>
<p>
In this sample, the "Product" column uses <input /> as the editor.
</p>
<p>
To get the binding column in the event handler, please use the MultiRow's <b>getBindingColumn</b> function.
</p>
</li>
<li>
<b>Use grid's internal editor.</b>
<p>
In this sample, "Amount2" and "Active" use grid internal editor. You don't need do anything.
</p>
</li>
</ul>
}