Не так давно у меня появилась необходимость в создать контекстное меню с настраиваемым
из code-behind числом элементов для моего ASP.NET MVC приложения. Потраченные
полчаса на поиск готового решения не увенчались успехом, в связи чем пришлось
заниматься созданием данной функциональности самостоятельно. О том что у меня
получилось я хочу рассказать в своей статье.
Итак за основу для решения задачи был взят простенький JQuery-плагин (http://www.trendskitchens.co.nz/jquery/contextmenu/)
который преобразует список div с находящимся в нем списком ul в
контекстное меню. С динамической генерацией списка проблем нет, более сложным выглядел
вопрос динамического создания байндинга обработчиков элементов меню. Но как
оказалось это тоже вопрос пяти минут. В итоге получилось простое и достаточно
эффективное решение.
Для демонстрации я создал простенькое приложение. При нажатии на зеленую
область правой кнопкой мыши появляется меню:
При нажатии на один из элементов меню появляется всплывающее окно с
сообщением. В случае представленном ниже мы выбрали меню “Save”.
Итак, пару слов о
реализации.
Первым делом
подключаем JQuery и
плагин контекстного меню:
<script src="~/Scripts/jquery-1.8.0.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery-ui-1.8.23.custom.min.js"
type="text/javascript"></script>
<script src="~/Scripts/jquery.contextmenu.r2.packed.js"
type="text/javascript"></script>
В контроллере
инициализируем коллекцию элементов меню:
public ActionResult
Test()
{
ViewBag.MenuItems
= new[] { "Open",
"Save", "Edit",
"Exit" };
return View();
}
В отображении
создаем два слоя, первый слой – зеленая область, второй слой – контекстное меню,
там генерируем список элементов, которые получили от контроллера:
@{
var mi = (IEnumerable<string>)ViewBag.MenuItems;
}
<div id="mainDiv">
<p>Right click here</p>
</div>
<div class="contextMenu" id="myMenu1">
<ul>
@foreach
(var item in
mi)
{
<li id="@item"><img src="@Url.Content("~/Content/images/edit.png")" />@item</li>
}
</ul>
</div>
Добавляем стиль
для первого слоя в Site.css:
#mainDiv {
width: 300px;
height: 300px;
background: limegreen;
}
Итак, все что теперь осталось это подключить плагин и настроить байндинг
обработчиков. Суть моего решения заключается в том, что мы на лету для каждого
элемента меню генерируем соответствующий элемент в байндинге. Обработчиком
каждого из элементов будет функция которая просто выводит название элемента
меню, который был выбран. Код представленный ниже демонстрирует реализацию.
<script type="text/javascript">
$(function () {
$('#mainDiv').contextMenu('myMenu1',
{
@if(mi.Any())
{
Html.ViewContext.Writer.WriteLine("bindings: {");
int count = mi.Count();
int i = 1;
foreach(var
item in mi)
{
Html.ViewContext.Writer.WriteLine(string.Format("'{0}': function(t) {{ menuHandler('{0}'); }}{1}",
item, i == count ? string.Empty : ","));
i++;
}
Html.ViewContext.Writer.WriteLine("}");
}
});
});
function menuHandler(obj)
{
alert('You can handle
menu for "' + obj + '" as you wish');
}
</script>
Вот и все. Потратив полчаса на реализацию я получил вполне хорошее решение,
которое позволяет полностью решить все мои потребности. Надеюсь для вас оно
окажется не менее полезным и так же сможет пригодится в случае необходимости
реализации подобной функциональности.
Комментариев нет:
Отправить комментарий