نمایش رکوردها به ترتیب اولویت به کمک jQuery UI sortable در ASP.NET MVC
نویسنده: امیرحسین مرجانی
تاریخ: ۱۳۹۱/۰۹/۰۸ ۲۰:۴۷
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
همان طور که میدانید کاربرد پذیری در خیلی از
پروژهها حرف اول رو میزند و کاربر دوست دارد کارهایی که انجام میدهد خیلی راحت
و با استفاده از موس باشد.یکی از کار هایی که در اکثر پروژهها نیاز است ، چیدمان
ترتیب رکوردها است. ما میخواهیم در این پست ترتیبی اتخاذ کنیم که کاربر بتواند رکوردها را به هر ترتیبی که دوست دارد نمایش دهد.
از توضیحاتی که قبلا دادم مشخص است که این کار احتمالا در ASP.NET WebForm کار سختی نیست ولی این کار باید در MVC از ابتدا طراحی شود.
طرح سوال : یک سری رکورد از یک Table داریم که میخواهیم به ترتیب وارد شدن رکوردها نباشد و ترتیبی که ما میخواهیم نمایش داده شود.
پاسخ کوتاه : خب باید ابتدا یک فیلد (برای اولویت بندی) به Table اضافه کنیم بعد اون فیلد رو بنا به ترتیبی که دوست داریم رکوردها نمایش داده شود پر کنیم (Sort می کنیم ) و در آخر هم هنگام نمایش در View رکوردها را بر اساس این فیلد نمایش میدهیم.
(این پست هم در ادامه پست قبلی در همان پروژه است و از همان Table ها استفاده شده است)
اضافه کردن فیلد :
ابتدا یک فیلد به Table مورد نظر اضافه میکنیم. من اسم این فیلد رو Priority گذاشتم. Table من چنین وضعیتی دارد.
افزودن فایلهای jQuery UI :
در این مرحله شما نیاز دارید فایلهای مورد نیاز برای Sort کردن رکوردها را اضافه کنید. شما میتوانید فقط فایلهای مربوط به Sortable را به صفحه خودتان اضافه کنید و یا مثل من فایل هایی که حاوی تمام قسمتهای jQuery UI هست را اضافه کنید.
من برای این کار از Section استفاده کردم ، ابتدا در Head فایل Layout دو Section تعریف کردم برای CSS و JavaScript . و فایلهای مربوط به Sort کردن را در صفحه ای که باید عمل Sort انجام بشود در این Section ها قرار دادم.
فایل Layout
<head>
<meta charset="utf-8" />
@RenderSection("meta", false)
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/~Site.css")" rel="stylesheet" type="text/css" />
<link href="@Url.Content("~/Content/redactor/css/redactor.css")" rel="stylesheet" type="text/css" />
<link href="@Url.Content("~/Content/css/bootstrap-rtl.min.css")" rel="stylesheet" type="text/css" />
@RenderSection("css", false)
<script src="@Url.Content("~/Scripts/jquery-1.8.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Content/js/bootstrap-rtl.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Content/redactor/redactor.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
@RenderSection("js", false)
</head>
فایل Index.chtml در پوشه کنترلر Type
@model IEnumerable<KhazarCo.Models.Type>
@{
ViewBag.Title = "Index";
Layout = "~/Areas/Administrator/Views/Shared/_Layout.cshtml";
}
@section css
{<link href="@Url.Content("~/Content/themes/base/jquery-ui.css")" rel="stylesheet" type="text/css" />
}
@section js
{
<script src="@Url.Content("~/Scripts/jquery-ui-1.9.0.min.js")" type="text/javascript"></script>
}
در آخر فایل Index.chtml به اینصورت شده است:
<h2>
نوع ها</h2>
<p>
@Html.ActionLink("ایجاد یک مورد جدید", "Create", null, new { @class = "btn btn-info" })
</p>
<table>
<thead>
<tr>
<th>
عنوان
</th>
<th>
توضیحات
</th>
<th>
فعال
</th>
<th>
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.OrderBy(m => m.Priority))
{
<tr id="@item.Id">
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@(new HtmlString(item.Description))
</td>
<td>
@Html.DisplayFor(modelItem => item.IsActive)
</td>
<td>
@Html.ActionLink("ویرایش", "Edit", new { id = item.Id }, new { @class = "btnEdit label label-warning" })
|
@Html.ActionLink("مشاهده", "Details", new { id = item.Id }, new { @class = "btnDetails label label-info" })
|
@Html.ActionLink("حذف", "Delete", new { id = item.Id }, new { @class = "btnDelete label label-important" })
</td>
</tr>
}
</tbody>
</table>
** توجه داشته باشید که من به هر tr یک id اختصاص داده ام که این مقدار id همان مقدار فیلد Id همان رکورد هست ، ما برای مرتب کردن به این Id نیاز داریم (خط 25).
افزودن کدهای کلاینت:
حالا باید کدی بنویسم که دو کار را برای ما انجام دهد : اول حالت Sort پذیری را به سطرهای Table بدهد و دوم اینکه هنگامی که ترتیب سطرهای تغییر کرد ما را با خبر کند:
<script type="text/javascript">
$(function () {
$("table tbody").sortable({
helper: fixHelper,
update: function (event, ui) {
jQuery.ajax('@Url.Action("Sort", "Type", new { area = "Administrator" })', {
data: { s: $(this).sortable('toArray').toString() }
});
}
}).disableSelection();
});
var fixHelper = function (e, ui) {
ui.children().each(function () {
$(this).width($(this).width());
});
return ui;
};
</script>
توضیح کد :
در این کد ما حالت ترتیب پذیری را به Table می دهیم و هنگامی که عمل Update در Table انجام شد تابع مربوطه اجرا میشود. ما در این تایع، ترتیب جدید سطرها را میگیریم ( ** به کمک مقدار Id که به هر سطر دادیم ، این مقدار Id برابر بود با Id خود رکورد در Database ) و به کمکjQuery.ajax به تابع Sort از کنترلر Type در منطقه (area ) Administrator ارسال میکنیم و در آنجا ادامه کار را انجام میدهیم.
تابع fixHelper هم به ما کمک میکند که هنگامی که سطرها از جای خود جدا میشوند ، دارای عرض یکسانی باشند و عرض آنها تغییری نکند.
افزودن کد Server:
حالا باید تابع Sort که مقادیر را به آن ارسال کردیم بنویسم. من این تابع را بر اساس مقداری که از کلاینت ارسال میشود اینگونه طراحی کردم.
public EmptyResult Sort(string s)
{
if (s != null)
{
var ids = new List<int>();
foreach (var item in s.Split(','))
{
ids.Add(int.Parse(item));
}
int intpriority = 0;
foreach (var item in ids)
{
intpriority++;
db.Types.Single(m => m.Id == item).Priority = intpriority;
}
db.SaveChanges();
}
return new EmptyResult();
}
در ایتدا مقادیر Id که از کلاینت به صورت String ارسال شده است را میگیریم و بعد به همان ترتیب ارسال در لیستی از int قرار میدهیم ids.
سپس به اضای هر رکورد Type مقدار اولویت را به فیلدی که برای همین مورد اضافه کردیم Priority اختصاص میدهیم. و در آخر هم تغییرات را ذخیره میکنیم. (خود کد کاملا واضح است و نیاری به توضیح بیشتر نیست )
حالا باید هنگامی که لیست Type ها نمایش داده میشود به ترتیب (OrderBy) فیلد Priority نمایش داده شود پس تابع Index را اینطور تغییر میدهیم.
public ViewResult Index()
{
return View(db.Types.Where(m => m.IsDeleted == false).OrderBy(m => m.Priority));
}
این هم خروجی کار من:
این عکس مربوط به است به قسمت مدیریت پروژه شیرآلات مرجان خزر.
«این کار احتمالا در ASP.NET WebForm کار سختی نیست»
اتفاقا کار سادهای نیست و همین مراحل باید طی شود. ضمن اینکه کار با jquery ajax در آنجا به این یک دستی نیست. نیاز است در code behind فرم، متد وب سرویس مانندی به صورت استاتیک تعریف شود (که خودش سبب میشود تا دسترسی به اعتبار سنجی توکار مبتنی بر فرمها محدود شود) یا اینکه از یک هندلر مجزا بجای یک اکشن متد کمک گرفته شود ... خلاصه خیلی داستان دارد.
بسیار عالی.
فقط در مورد update panel ... تنها کاری که انجام میدهد کپسوله کردن ارسال مقادیر به سرور است به صورت ajax سازگار با کنترلهای دارای view state . بیشتر از این کاری انجام نمیدهد. مابقی آن اگر یک سری کنترل در toolkit آن موجود باشد برای این کارها یا خیر. این toolkit هم محدود است و آنچنان به روز نمیشود.
@model IEnumerable<KhazarCo.Models.Type>
فقط mvc هست که امکان استفاده از چند view engine را با هم دارد.
صفحهای که لینک دادید مربوط است به asp.net web pages و نه web forms. این web pages برای کار با webmatrix طراحی شده.
<iframe src="/twitter" frameborder="0" height="400" width="270" scrolling="no"></iframe>
فلسفه و کاربرد web pages متفاوت است. در مورد وب فرمها هم نمیتونید از razor استفاده کنید چون در یک فایل نمیشود از دو موتور view استفاده کرد. موتور view وب فرمها، نامش همین web forms view engine است و قابل تعویض هم نیست (برخلاف MVC). در مقالهای که لینک دادید، داره از یک iframe استفاده میکنه برای الحاق razor.
به علاوه در مورد Web API که کلا مطلب جدیدی نیست. نسخه ساده شده WCF است.
razor بیجهت اینجا طرح شد. من در مورد strongly typed view سطری رو نوشتم. این نوع viewها مستقل از نوع view engine هستند. در mvc حتی با موتور web forms هم میشه یک چنین viewهای تحت نظر کامپایلری رو با پشتیبانی کامل از intelisense داشت.