Undo
Undo
元に戻すスタック
このビューは、UndoStackの使用方法を示します。
機能
サンプル
説明
UndoStackクラスを使用すると、ページ、フォーム、任意の要素で元に戻す/やり直しを行うことができます。通常のHTML入力要素やほとんどのMVCコントロールへの変更を追跡し、元に戻す/やり直しのショートカットキーを自動的に処理し、元に戻す/やり直しの操作をプログラムで実行するためのコマンドを提供します。
ソース
IndexController.cs
using MvcExplorer.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcExplorer.Controllers
{
public partial class UndoController : Controller
{
public ActionResult Index(FormCollection data)
{
return View(Sale.GetData(50));
}
}
}
Index.cshtml
@model IEnumerable<Sale>
@{
var selectValues = Resources.Undo.UndoStack_Form_Text4.Split(';');
var checkValues = Resources.Undo.UndoStack_Form_Text6.Split(';');
var radioValues = Resources.Undo.UndoStack_Form_Text7.Split(';');
}
<div class="container-fluid">
<!-- Undo/Redo Toolbar -->
<div class="toolbar">
<button id="undo" class="btn btn-primary" disabled>
<span class="arrow">↶</span>@Html.Raw(Resources.Undo.UndoStack_Toolbar_Text0)
</button>
<button id="redo" class="btn btn-primary" disabled>
<span class="arrow">↷</span>@Html.Raw(Resources.Undo.UndoStack_Toolbar_Text1)
</button>
<button class="btn" disabled>
@Html.Raw(Resources.Undo.UndoStack_Toolbar_Text2)<span id="undo-cnt">0</span>
</button>
<button id="clear" class="btn btn-default" disabled>
@Html.Raw(Resources.Undo.UndoStack_Toolbar_Text3)
</button>
</div>
<!-- Undo/Redo Form -->
<form id="undoable-form">
<div class="row">
<!-- HTML Input elements -->
<div class="col-md-3">
<h3>@Html.Raw(Resources.Undo.UndoStack_Form_Text0)</h3>
<div class="form-group">
<label for="firstName">@Html.Raw(Resources.Undo.UndoStack_Form_Text1)</label>
<input id="firstName" class="form-control" placeholder="@Html.Raw(Resources.Undo.UndoStack_Form_Text1)" />
</div>
<div class="form-group">
<label for="lastName">@Html.Raw(Resources.Undo.UndoStack_Form_Text2)</label>
<input id="lastName" class="form-control" placeholder="@Html.Raw(Resources.Undo.UndoStack_Form_Text2)" />
</div>
<div class="form-group">
<label for="select">@Html.Raw(Resources.Undo.UndoStack_Form_Text3) (Select)</label>
<select id="select" class="form-control">
@for (int i = 1; i < 4; i++)
{
if (i == 2)
{
<option value=@("value"+i) selected>@selectValues[i - 1]</option>
}
else
{
<option value=@("value"+i)>@selectValues[i - 1]</option>
}
}
</select>
</div>
<div class="form-group">
<label for="area">@Html.Raw(Resources.Undo.UndoStack_Form_Text5) (TextArea)</label>
<textarea id="area" class="form-control" placeholder="@Html.Raw(Resources.Undo.UndoStack_Form_Text5)"></textarea>
</div>
<div class="form-group label-indent">
@for (int i = 1; i < 4; i++)
{
<label class="checkbox-inline">
<input type="checkbox" id=@("inlineCheckbox"+i) value=@("option"+i) checked="@(i == 1)">
@checkValues[i - 1]
</label>
}
</div>
<div class="form-group label-indent">
@for (int i = 1; i < 4; i++)
{
<label class="radio-inline">
<input type="radio" name="inlineRadioOptions" id=@("inlineRadio"+i) value=@("option"+i) checked="@(i == 1)">
@radioValues[i - 1]
</label>
}
</div>
</div>
<!-- MVC controls -->
<div class="col-md-3">
<h3>@Html.Raw(Resources.Undo.UndoStack_Form_Text10)</h3>
<div class="form-group">
<label for="country">@Html.Raw(Resources.Undo.UndoStack_Form_Text11) (ComboBox)</label>
<div id="country" placeholder="@Html.Raw(Resources.Undo.UndoStack_Form_Text11)"></div>
</div>
<div class="form-group">
<label for="date">@Html.Raw(Resources.Undo.UndoStack_Form_Text13) (InputDate)</label>
<div id="date" placeholder="@Html.Raw(Resources.Undo.UndoStack_Form_Text13)"></div>
</div>
<div class="form-group">
<label for="amount">@Html.Raw(Resources.Undo.UndoStack_Form_Text12) (InputNumber)</label>
<div id="amount" placeholder="@Html.Raw(Resources.Undo.UndoStack_Form_Text12)"></div>
</div>
<div class="form-group">
<label for="ac" title="AutoComplete">@Html.Raw(Resources.Undo.UndoStack_Form_Text14) (AutoComplete)</label>
<div id="ac"></div>
</div>
<div class="form-group">
<label for="colors" title="MultiSelect">@Html.Raw(Resources.Undo.UndoStack_Form_Text15) (MultiSelect)</label>
<div id="colors"></div>
</div>
<div class="form-group">
<label for="mac" title="MultiAutoComplete">@Html.Raw(Resources.Undo.UndoStack_Form_Text15) (MultiAutoComplete)</label>
<div id="mac"></div>
</div>
</div>
<!-- MVC controls more -->
<div class="col-md-6">
<h3 class="wide-screen"> </h3>
<div class="form-group">
<label for="gauge">Gauge</label>
<div id="gauge"></div>
</div>
<div class="form-group">
<label for="grid">Grid</label>
<div id="grid"></div>
<button id="add-row" class="btn btn-primary">
@Html.Raw(Resources.Undo.UndoStack_Form_Text17)
</button>
<button id="del-row" class="btn btn-primary">
@Html.Raw(Resources.Undo.UndoStack_Form_Text18)
</button>
<label class="inline-label">
@Html.Raw(Resources.Undo.UndoStack_Form_Text19)
<input id="nr-top" class="wj-no-undo" type="checkbox">
</label>
</div>
</div>
</div>
</form>
</div>
@(Html.C1().ComboBox("#country").Bind(Sale.GetCountries()).IsRequired(false))
@(Html.C1().InputNumber("#amount").Format("c2").Min(0).Step(10).Value(null).IsRequired(false))
@(Html.C1().InputDate("#date").Value(null).IsRequired(false))
@(Html.C1().AutoComplete("#ac").Bind(Sale.GetColors()))
@(Html.C1().MultiSelect("#colors").Bind(Sale.GetColors()))
@(Html.C1().MultiAutoComplete("#mac").Bind(Sale.GetColors()))
@(Html.C1().RadialGauge("#gauge")
.Thickness(0.2)
.Min(0)
.Max(100)
.Value(50)
.IsReadOnly(false)
.TickSpacing(10)
.ShowTicks(true)
.ShowText(ShowText.Value)
.NeedleShape(NeedleShape.Outer)
.NeedleLength(NeedleLength.Inner)
)
@(Html.C1().FlexGrid<Sale>("#grid")
.AutoGenerateColumns(false)
.Id("grid")
.CssClass("grid")
.AllowAddNew(true)
.AllowDelete(true)
.Bind(b => b.Bind(Model).DisableServerRead(true))
.Columns(bl =>
{
bl.Add(cb => cb.Binding("ID"));
bl.Add(cb => cb.Binding("Start"));
bl.Add(cb => cb.Binding("End"));
bl.Add(cb => cb.Binding("Country")
.DataMap(dm => dm.DisplayMemberPath("Name")
.SelectedValuePath("Name")
.SortByDisplayValues(true)
.Bind(FullCountry.GetCountries())));
bl.Add(cb => cb.Binding("Product")
.DataMap(dm => dm.DisplayMemberPath("Name")
.SelectedValuePath("Name")
.SortByDisplayValues(true)
.Bind(ProductObject.GetProductObjects())));
bl.Add(cb => cb.Binding("Color")
.DataMap(dm => dm.DisplayMemberPath("Name")
.SelectedValuePath("Name")
.SortByDisplayValues(true)
.Bind(ColorObject.GetColorObjects())));
bl.Add(cb => cb.Binding("Amount").Format("c"));
bl.Add(cb => cb.Binding("Amount2").Format("c"));
bl.Add(cb => cb.Binding("Discount").Format("p0"));
bl.Add(cb => cb.Binding("Active"));
})
)
@section Styles{
<style>
.toolbar {
position: sticky;
top: 0;
z-index: 10;
padding: 12px;
margin-left: -12px;
background: #eee;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.arrow {
display: inline-block;
transform: scale(2);
margin-right: 8px;
}
.form-group label {
min-width: 100px;
}
.inline-label {
display: inline-block;
max-width: 100%;
margin-bottom: 5px;
font-weight: 700;
}
.label-indent {
margin-left: 0px;
}
.label-indent label {
min-width: 0;
}
.form-control {
display: inline-block;
width: 100%;
max-width: 300px;
}
.btn {
outline: none !important;
}
.wj-dropdown, .wj-inputnumber {
width: 100%;
max-width: 300px;
}
.wj-multi-autocomplete {
width: 100%;
max-width: 400px;
}
.wj-flexgrid {
height: 250px;
}
.wj-radialgauge {
display: table;
max-width: 100%;
margin: 0 auto;
}
.wj-gauge .wj-needle {
fill: orangered;
stroke: orangered;
}
.wj-gauge .wj-needle .wj-inner-needle-cap {
fill: white;
}
</style>
}
@section Scripts{
<script>
var selects, checks, radios;
c1.documentReady(function () {
// Create undo stack
let undoStack = new wijmo.undo.UndoStack('#undoable-form', {
maxActions: 50,
stateChanged: function(s) {
btnUndo.disabled = !s.canUndo;
btnRedo.disabled = !s.canRedo;
btnClear.disabled = !s.actionCount;
cnt.textContent = s.actionCount.toString();
},
});
// Config Add/Delete grid row buttons
let g = wijmo.Control.getControl("#grid");
document.getElementById('add-row').addEventListener('click', function (e) {
g.focus();
let view = g.editableCollectionView;
let newItem = view.addNew();
newItem.ID = -1;
newItem.Start = new Date();
newItem.End = new Date();
newItem.active = true;
g.onRowAdded(new wijmo.grid.CellRangeEventArgs(g.cells, g.selection)); // create undoable action
view.commitNew();
e.preventDefault(); // don't submit the form
});
document.getElementById('del-row').addEventListener('click', function (e) {
g.focus();
let view = g.editableCollectionView;
if (view.items.length) {
let sel = g.selection;
if (sel.row > -1) {
let item = g.rows[sel.row].dataItem;
g.onDeletingRow(new wijmo.grid.CellRangeEventArgs(g.cells, g.selection)); // create undoable action
view.remove(item);
}
}
e.preventDefault(); // don't submit the form
});
document.getElementById('nr-top').addEventListener('click', function (e) {
g.newRowAtTop = e.target.checked;
});
// Configs undo/redo buttons
let btnUndo = document.getElementById('undo');
let btnRedo = document.getElementById('redo');
let btnClear = document.getElementById('clear');
let cnt = document.getElementById('undo-cnt');
btnUndo.addEventListener('click', function () {
undoStack.undo();
});
btnRedo.addEventListener('click', function () {
undoStack.redo();
});
btnClear.addEventListener('click', function () {
undoStack.clear();
});
});
</script>
}
@section Summary{
<p>@Html.Raw(Resources.Undo.UndoStack_Text0)</p>
}
@section Description{
<p>@Html.Raw(Resources.Undo.UndoStack_Text1)</p>
}
マニュアル