MVC DevExpress Radio button list for Model - asp.net-mvc

I have a model class as shown below
public class AddKeyModel
{
public int Count { get; set; }
/// <summary>
/// 0 - Trial
/// 1 - License
/// </summary>
public bool LicenseType { get; set; }
/// <summary>
/// 0 - Lite
/// 1 - Pro
/// </summary>
public int ProductType { get; set; }
}
I am using DevExpress MVC extensions but facing problem in displaying this data on view. can anybody tell me the exact code to show radio buttons and also set back the data to model while submitting data to controller.
this code is not working
#Html.DevExpress().RadioButton(
settings =>
{
settings.Name = "Trial";
settings.GroupName = "LicenseType";
}).Bind(Model.LicenseType).GetHtml()
#Html.DevExpress().Label(
settings =>
{
settings.ControlStyle.CssClass = "label";
settings.Text = "License";
settings.AssociatedControlName = "License";
}).GetHtml()
#Html.DevExpress().RadioButton(
settings =>
{
settings.Name = "License";
settings.GroupName = "LicenseType";
}).Bind(Model.LicenseType).GetHtml()

You can use RadioButtonList instead.
See the How to use the CheckBoxList and RadioButtonList editors to edit Model fields example.

Related

How to maximize TableViewCell reactive binding performances?

I'm currently working on an Xamarin based app for iOS.
Among other features, the app is displaying items in a tableview (pretty classic). I noticed that the binding performance was quite bad, as scrolling really fast the table view will show some lag.
I've created a really simple project replicating the issue, available on Github.
To sum up briefly.
This project has an implementation for each of the following viewmodel interface:
public interface IItemViewModel : INotifyPropertyChanged, IActivatableViewModel
{
/// <summary>
/// A title
/// </summary>
string Title { get; }
/// <summary>
/// A value
/// </summary>
string Value { get; }
}
public interface IItemListViewModel : INotifyPropertyChanged, IActivatableViewModel
{
/// <summary>
/// Minimun count of items possible in the <see cref="Items"/> collection
/// </summary>
int MinItems { get; }
/// <summary>
/// Maximum count of items possible in the <see cref="Items"/> collection
/// </summary>
int MaxItems { get; }
/// <summary>
/// <see cref="Items"/>'s count.
/// Changing the value will update the <see cref="Items"/> collection accordingly.
/// </summary>
int ItemCount { get; set; }
ReadOnlyObservableCollection<IItemViewModel> Items { get; }
}
The view is implemented on iOS using one UIViewController displaying the VM's collection in a UITableView. A slider is bound to the VM's ItemCount property to update easily the item collection's count.
The ViewController is implemented as follow:
public partial class ViewController : ReactiveViewController<IItemListViewModel>
{
public ViewController(IntPtr intPtr) : base(intPtr)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.ItemTableView.RegisterNibForCellReuse(ItemViewCell.Nib, ItemViewCell.Key);
this.WhenActivated(disposables =>
{
this.Bind(this.ViewModel, vm => vm.ItemCount, v => v.ItemCountSlider.Value, v => (float)Convert.ToDouble(v), Convert.ToInt32)
.DisposeWith(disposables);
this.OneWayBind(this.ViewModel, vm => vm.ItemCount, v => v.ItemCountLabel.Text, Convert.ToString)
.DisposeWith(disposables);
this.WhenAnyValue(x => x.ViewModel.Items)
.BindTo<ItemViewModel, ItemViewCell>(this.ItemTableView, ItemViewCell.Key, 80, cell => cell.Initialize())
.DisposeWith(disposables);
});
this.ViewModel = new ItemListViewModel();
this.ItemCountSlider.MinValue = this.ViewModel.MinItems;
this.ItemCountSlider.MaxValue = this.ViewModel.MaxItems;
}
}
And the ViewCell rendering the IItemViewModel is:
public partial class ItemViewCell : ReactiveTableViewCell<IItemViewModel>
{
public static readonly NSString Key = new NSString("ItemViewCell");
public static readonly UINib Nib = UINib.FromName("ItemViewCell", NSBundle.MainBundle);
protected ItemViewCell(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
this.WhenActivated(disposables =>
{
this.OneWayBind(this.ViewModel, vm => vm.Title, v => v.TitleLabel.Text)
.DisposeWith(disposables);
this.OneWayBind(this.ViewModel, vm => vm.Value, v => v.ValueLabel.Text)
.DisposeWith(disposables);
});
}
public void Initialize()
{
}
}
When I deploy the app on an iPad 4, set the collection item count to something like few thousands, scrolling (very) fast become quite "laggy".
I know the device is old (built late 2015). But in my test project only two properties are bound to the ViewCell UI components.
In my real app, the viewmodel exposes around 10 properties, thus the lag appears as well on modern devices like the iPad pro.
I'm wondering if there is a better way to perform view cell bindings, or is it a technical limitation?
Thanks.

ASP.NET MVC 5 Showing 10 rows out of 500 records in Jquery Datatables With Server Side Processing

I Have a problem with my Jquery datatables. It shows only the first 10 rows out of 500 records in my database. Can someone help me to solve this problem.
Here is my code :
CONTROLLER :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI.WebControls;
using WinWin.Models;
namespace WinWin.Controllers
{
public class PostController : Controller
{
[Route("post")]
public ActionResult Index()
{
return View();
}
[Route("post/ajaxpost")]
public JsonResult ajaxpost(DTParameters param)
{
try
{
using (WintayoEntities db = new WintayoEntities())
{
var source = new List<Post>();
foreach (var p in db.ccp_post.ToList())
{
source.Add(new Post
{
id = p.post_id,
title = p.title,
date = p.post_on.ToString("yyyy-MM-dd"),
views = p.pageviews,
published = (p.is_published == 0) ? "Draft" : "Published",
featured = (p.is_featured == 0) ? "No" : "Yes",
action = string.Format(#"<i class=""fa fa-edit""></i> <i class=""fa fa-trash-o""></i>")
});
}
List<String> columnSearch = new List<String>();
foreach (var col in param.Columns)
{
columnSearch.Add(col.Search.Value);
}
List<Post> data = new ResultPost().GetResult(param.Search.Value, param.SortOrder, param.Start, param.Length, source, columnSearch);
int count = new ResultPost().Count(param.Search.Value, data, columnSearch);
DTResult<Post> result = new DTResult<Post>
{
draw = param.Draw,
data = data,
recordsFiltered = count,
recordsTotal = count
};
return Json(result);
}
}
catch (Exception e)
{
return Json(new { error = e.Message });
}
}
}
}
DATATABLE VIEW MODEL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WinWin.Models
{
/// <summary>
/// A full result, as understood by jQuery DataTables.
/// </summary>
/// <typeparam name="T">The data type of each row.</typeparam>
public class DTResult<T>
{
/// <summary>
/// The draw counter that this object is a response to - from the draw parameter sent as part of the data request.
/// Note that it is strongly recommended for security reasons that you cast this parameter to an integer, rather than simply echoing back to the client what it sent in the draw parameter, in order to prevent Cross Site Scripting (XSS) attacks.
/// </summary>
public int draw { get; set; }
/// <summary>
/// Total records, before filtering (i.e. the total number of records in the database)
/// </summary>
public int recordsTotal { get; set; }
/// <summary>
/// Total records, after filtering (i.e. the total number of records after filtering has been applied - not just the number of records being returned for this page of data).
/// </summary>
public int recordsFiltered { get; set; }
/// <summary>
/// The data to be displayed in the table.
/// This is an array of data source objects, one for each row, which will be used by DataTables.
/// Note that this parameter's name can be changed using the ajaxDT option's dataSrc property.
/// </summary>
public List<T> data { get; set; }
}
/// <summary>
/// The additional columns that you can send to jQuery DataTables for automatic processing.
/// </summary>
public abstract class DTRow
{
/// <summary>
/// Set the ID property of the dt-tag tr node to this value
/// </summary>
public virtual string DT_RowId
{
get { return null; }
}
/// <summary>
/// Add this class to the dt-tag tr node
/// </summary>
public virtual string DT_RowClass
{
get { return null; }
}
/// <summary>
/// Add this data property to the row's dt-tag tr node allowing abstract data to be added to the node, using the HTML5 data-* attributes.
/// This uses the jQuery data() method to set the data, which can also then be used for later retrieval (for example on a click event).
/// </summary>
public virtual object DT_RowData
{
get { return null; }
}
}
/// <summary>
/// The parameters sent by jQuery DataTables in AJAX queries.
/// </summary>
public class DTParameters
{
/// <summary>
/// Draw counter.
/// This is used by DataTables to ensure that the Ajax returns from server-side processing requests are drawn in sequence by DataTables (Ajax requests are asynchronous and thus can return out of sequence).
/// This is used as part of the draw return parameter (see below).
/// </summary>
public int Draw { get; set; }
/// <summary>
/// An array defining all columns in the table.
/// </summary>
public DTColumn[] Columns { get; set; }
/// <summary>
/// An array defining how many columns are being ordering upon - i.e. if the array length is 1, then a single column sort is being performed, otherwise a multi-column sort is being performed.
/// </summary>
public DTOrder[] Order { get; set; }
/// <summary>
/// Paging first record indicator.
/// This is the start point in the current data set (0 index based - i.e. 0 is the first record).
/// </summary>
public int Start { get; set; }
/// <summary>
/// Number of records that the table can display in the current draw.
/// It is expected that the number of records returned will be equal to this number, unless the server has fewer records to return.
/// Note that this can be -1 to indicate that all records should be returned (although that negates any benefits of server-side processing!)
/// </summary>
public int Length { get; set; }
/// <summary>
/// Global search value. To be applied to all columns which have searchable as true.
/// </summary>
public DTSearch Search { get; set; }
/// <summary>
/// Custom column that is used to further sort on the first Order column.
/// </summary>
public string SortOrder
{
get
{
return Columns != null && Order != null && Order.Length > 0
? (Columns[Order[0].Column].Data + (Order[0].Dir == DTOrderDir.DESC ? " " + Order[0].Dir : string.Empty))
: null;
}
}
}
/// <summary>
/// A jQuery DataTables column.
/// </summary>
public class DTColumn
{
/// <summary>
/// Column's data source, as defined by columns.data.
/// </summary>
public string Data { get; set; }
/// <summary>
/// Column's name, as defined by columns.name.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Flag to indicate if this column is searchable (true) or not (false). This is controlled by columns.searchable.
/// </summary>
public bool Searchable { get; set; }
/// <summary>
/// Flag to indicate if this column is orderable (true) or not (false). This is controlled by columns.orderable.
/// </summary>
public bool Orderable { get; set; }
/// <summary>
/// Specific search value.
/// </summary>
public DTSearch Search { get; set; }
}
/// <summary>
/// An order, as sent by jQuery DataTables when doing AJAX queries.
/// </summary>
public class DTOrder
{
/// <summary>
/// Column to which ordering should be applied.
/// This is an index reference to the columns array of information that is also submitted to the server.
/// </summary>
public int Column { get; set; }
/// <summary>
/// Ordering direction for this column.
/// It will be dt-string asc or dt-string desc to indicate ascending ordering or descending ordering, respectively.
/// </summary>
public DTOrderDir Dir { get; set; }
}
/// <summary>
/// Sort orders of jQuery DataTables.
/// </summary>
public enum DTOrderDir
{
ASC,
DESC
}
/// <summary>
/// A search, as sent by jQuery DataTables when doing AJAX queries.
/// </summary>
public class DTSearch
{
/// <summary>
/// Global search value. To be applied to all columns which have searchable as true.
/// </summary>
public string Value { get; set; }
/// <summary>
/// true if the global filter should be treated as a regular expression for advanced searching, false otherwise.
/// Note that normally server-side processing scripts will not perform regular expression searching for performance reasons on large data sets, but it is technically possible and at the discretion of your script.
/// </summary>
public bool Regex { get; set; }
}
}
VIEW
<div class="contentpanel">
<div class="panel panel-default">
<div class="panel-body">
<div class="table-responsive">
<table class="table mb30 table-class-ajax" data-list="post/ajaxpost">
<colgroup>
<col style="width: 4%;" />
<col style="width: auto;" />
<col style="width: 13%;" />
<col style="width: 9%;" />
<col style="width: 8%;" />
<col style="width: 8%;" />
<col style="width: 105px;" />
</colgroup>
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Publish Date</th>
<th>Pageviews</th>
<th>Featured</th>
<th>Published</th>
<th></th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div><!-- contentpanel -->
<script>
$(document).ready(function () {
var oTable = $(".table-class-ajax").DataTable({
"serverSide": true,
"ajax": {
"type": "POST",
"url": "post/ajaxpost",
"contentType": 'application/json; charset=utf-8',
'data': function (data) { return data = JSON.stringify(data); }
},
"processing": true,
"paging": true,
"pagingType": "full_numbers",
"deferRender": true,
"columns": [
{ "data": "id" },
{ "data": "title" },
{ "data": "date" },
{ "data": "views" },
{ "data": "featured" },
{ "data": "published" },
{ "data": "action" }
],
"order": [0, "asc"],
"info": true,
});
});
</script>
You got paging turned on in your client side script for your DataTable.
//...
"paging": false
//...
In Your code if you see Datatable view model the lenth parameter states the total coloumns to be loaded for the data table.
/// <summary>
/// Number of records that the table can display in the current draw.
/// It is expected that the number of records returned will be equal to this number, unless the server has fewer records to return.
/// Note that this can b**e -1 to** indicate that all records should be returned (although that negates any benefits of server-side processing!)
/// </summary>
public int **Length** { get; set; }
Set the value to -1 as said in the code

Most efficient way to render data into a form from a populated model

I've got a populated entity filled with checkbox selector, few strings. that has to be built linearly(for each row) in a loop in a div structure.
The entity:
public class Hours
{
[Key]
public int SliceID { get; set; }
public string SliceName { get; set; }
public string Slice { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public bool Selected { get; set; } //if slice is checked by user on search screen
}
The action which will gather all time slices for display:
public ActionResult Search_Times()
{
int iInstId = 1;
Test.Models.DataLayer db = new Test.Models.DataLayer();
Test.Models.TestDB context = new Models.TestDB();
IEnumerable<Test.Models.Hours> lst = db.GetSlices(context, iInstId).OrderBy(a => a.SliceID);
// ViewBag.SliceList = lst;
return View(lst);
}
I want to render those fields in a specific part of my body page along with some class/div formatting along the way.
For example, If I use EditorForModel :
in Main page:
#model IEnumerable<Test.Models.Hours>
#Html.EditorForModel()
in the Hours EditorTemplate:
#model Test.Models.Hours
<div>
#Html.CheckBoxFor(
x => x.Selected,
new {
#class = "jcf-unselectable",
id = HtmlHelper.GenerateIdFromName("cb_slice." + ViewData.TemplateInfo.GetFullHtmlFieldName(""))
}
)
// this should be a label too, made for example to show text from data.
#Html.DisplayTextFor(x => x.SliceName)
#Html.LabelFor(
x=> x.StartTime,
new {
#class = "info"
})
#Html.LabelFor(
x => x.EndTime,
new {
#class = "info"
})
</div>
The #Html.LabelFor in my case will only show the row's title and not the data (for="" in the source view after rendering), Unlike DisplayTextFor which will show the data but is only a generic text.
I need a way or to fix this current way, To manipulate the data from the model accordingly, Labels will show the data behind their field and I could generate the class,id needed(based on css/html required) inside that label in a loop.
What's the best way to do so, viewbags/templates/etc?

Telerik Rad Grid on ASP.NET MVC Razor view engine - DetailView not initially populating

OK...I've spent too much time floundering on this one, so I'm passing it on to the experts -> YOU.
My VERY simple ASP.NET MVC (v3 with Razor View Engine) page uses a Telerik Rad Grid control to show some type lists and then I have the associated codes showing in the DetailsView of the grid.
Doing the population is easy. I have a ViewModel for my TypeCodeList type and send it to the strongly typed view to populate the grid. This works GREAT...and the grid looks great - thanks Telerik. However, I added the DetailsView to then populate the child TypeCodes in the same manner. The bad thing is that when my grid populates, I select the triangle on the left to expand the tree and see the child records, nothing is there. BUT, if I select the "Refresh" button on the bottom of the grid, THEN I can hit the triangle and the child records display.
So (in summary), the child records do not show up on the initial load. Only when I select an AJAX refresh of the grid I get the children. Otherwise, it works as required.
I have been trying to see if I can programmatically kick off the refresh via javascrip upon page load. OR if I can get the thing to populate by itself when selected without doing a refresh first - that would be preferable.
Below is my code:
Pertinent Controller Code (I've taken out the update, delete, insert, logging and data access methods)
[HandleErrorWithElmah]
public partial class HostController : Controller
{
/// <summary>
/// Index - Home for HostController
/// </summary>
/// <returns></returns>
public ActionResult Index()
{
return View();
}
#region Type List Section
/// <summary>
/// Gets the list of TypeLists - yea...say that again
/// </summary>
[GridAction]
public ActionResult TypeCodeList()
{
var model = GetActiveTypeLists();
// Get all of the type lists and send them to the view
return View(model);
}
/// <summary>
/// The ajaxified Select
/// </summary>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult _TypeCodeList()
{
var model = GetActiveTypeLists();
return Json(new GridModel(model));
}
/// <summary>
/// Simply a wrapper to get all of the current type list values.
/// </summary>
/// <returns></returns>
private IEnumerable<TypeCodeListViewModel> GetActiveTypeLists()
{
var model = from p in entityRepository.Find<TypeList>(p => p.IsActive == true)
select new TypeCodeListViewModel
{
TypeListId = p.TypeListId,
Name = p.Name,
Description = p.Description,
IsActive = p.IsActive
};
return model;
}
#endregion
#region Type Code Section
[AcceptVerbs(HttpVerbs.Post)]
[GridAction]
public ActionResult _TypeCodeForTypeListAjax(int typeListId)
{
var model = GetActiveTypeCodes(typeListId);
return Json(new GridModel(model));
}
/// <summary>
/// Simply a wrapper to get all of the current type Code values.
/// </summary>
/// <returns></returns>
private IEnumerable<TypeCodeViewModel> GetAllActiveTypeCodes()
{
var model = from p in entityRepository.Find<OurLeaguePlay.Models.TypeCode>(p => p.IsActive == true).OrderBy(ord => ord.CodeName)
select new TypeCodeViewModel
{
TypeCodeId = p.TypeCodeId,
TypeListId = p.TypeListId,
CodeName = p.CodeName,
CodeValue = p.CodeValue,
Description = p.Description,
IsActive = p.IsActive
};
return model;
}
/// <summary>
/// Simply a wrapper to get all of the current type Code values.
/// </summary>
/// <returns></returns>
private IEnumerable<TypeCodeViewModel> GetActiveTypeCodes(int typeListId)
{
var model = from p in entityRepository.Find<OurLeaguePlay.Models.TypeCode>(p => p.IsActive == true &&
p.TypeListId == typeListId).OrderBy(ord => ord.CodeName)
select new TypeCodeViewModel
{
TypeCodeId = p.TypeCodeId,
TypeListId = p.TypeListId,
CodeName = p.CodeName,
CodeValue = p.CodeValue,
Description = p.Description,
IsActive = p.IsActive
};
return model;
}
#endregion
}
Here is my View Code:
(I've taken out all of my failed javascript attempts to try and force the load on page load.)
#model IEnumerable<TypeCodeListViewModel>
#using Telerik.Web.Mvc.UI
#using Telerik.Web.Mvc
#using OurLeaguePlay.ViewModels
#{Html.Telerik().Grid<TypeCodeListViewModel>(Model)
.Name("TypeLists")
.DetailView(details => details.ClientTemplate(
Html.Telerik().Grid<TypeCodeViewModel>()
.Name("TypeCode_<#= TypeListId #>")
.DataKeys(keys => keys.Add(k => k.TypeCodeId))
.Columns(columns =>
{
columns.Bound(o => o.CodeName).Width(40);
columns.Bound(o => o.CodeValue).ReadOnly(true).Width(40);
columns.Bound(o => o.Description).Width(100);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax().Select("_TypeCodeForTypeListAjax", "Host", new { typeListId = "<#= TypeListId #>" })
.Enabled(true);
}
)
.Pageable()
.Sortable()
.NoRecordsTemplate("No Type Codes exist for the selected Type List")
.ToHtmlString()
)
)
.DataKeys(keys => keys.Add(k => k.TypeListId))
.Columns(columns =>
{
columns.Bound(o => o.Name).Width(100);
columns.Bound(o => o.Description).Width(150);
columns.Command(commands =>
{
commands.Edit().ButtonType(GridButtonType.Image);
commands.Delete().ButtonType(GridButtonType.Image);
}
).Width(30);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax().Select("_TypeCodeList", "Host")
.Update("UpdateTypeList", "Host")
.Insert("InsertTypeList", "Host")
.Delete("DeleteTypeList", "Host")
.Enabled(true);
dataBinding.Server().Select("TypeCodeList", "Host", new { ajax = ViewData["ajax"] });
}
)
.Editable(editable => editable.Enabled(true).Mode(GridEditMode.InLine))
.Pageable(page => page.PageSize(10))
.Sortable()
.Selectable()
.Scrollable(scroll => scroll.Enabled(false))
.NoRecordsTemplate("No Type Lists can be retrieved from the database")
.ToolBar(commands => commands.Insert())
.Render();
}
Finally...here are the ViewModel classes:
public class TypeCodeListViewModel
{
[ScaffoldColumn(false)]
public int TypeListId { get; set; }
[Required(ErrorMessage = "Required")]
[StringLength(25, ErrorMessage = "Max Length is 25")]
public string Name { get; set; }
[Required(ErrorMessage = "Required")]
[StringLength(25, ErrorMessage="Max Length is 25")]
public string Description { get; set; }
[ScaffoldColumn(false)]
public bool IsActive { get; set; }
}
public class TypeCodeViewModel
{
[ScaffoldColumn(false)]
public int TypeCodeId { get; set; }
[ScaffoldColumn(false)]
public int TypeListId { get; set; }
[Required(ErrorMessage = "Required")]
[StringLength(25, ErrorMessage = "Max Length is 25")]
[DisplayName("Name")]
public string CodeName { get; set; }
[Required(ErrorMessage = "Required")]
[StringLength(25, ErrorMessage = "Max Length is 25")]
[DisplayName("Value")]
public string CodeValue { get; set; }
[StringLength(500, ErrorMessage = "Max Length is 500")]
public string Description { get; set; }
[ScaffoldColumn(false)]
public bool IsActive { get; set; }
}
Well...I think I figured it out on my own...it was as simple as just letting the grid bind itself and not forcing data into it via the non-ajax method that gets called upon initial display of the page.
The
Public ActionResult TypeCodeList()
function should simply be updated to the following:
Public ActionResult TypeCodeList()
{
return View();
}
with no [GridAction] decorator.
If you don't force values into the grid, it will bind itself using the Ajax method and then the child grids will populate upon expansion.

OneWay Databinding for ViewModel

I have some fields in my ViewModel that I only need for the output in my View. But they are always getting send when submitting the form. That's not only annoying, but also dangerous, because I definitly don't want that databinding for these viewmodel fields.
Are there any change to define a OneWay Databinding for some of my viewmodel properties?
Thx in advance
EDIT:
The problem ist, that the Pictures and ValidSizes List is send back to the server when I click to an ActionLink.
http://localhost:52176/?PageSize=30&Index=31&Pictures=System.Collections.Generic.List%601[System.String]&Size=100&ValidSizes=System.Collections.Generic.List%601[System.Web.Mvc.SelectListItem]
public class PicturesViewModel
{
public const int SMALL = 100;
public const int MIDDLE = 150;
public const int BIG = 250;
public int PageSize { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="PicturesViewModel"/> class.
/// </summary>
public PicturesViewModel()
{
Pictures = new List<string>();
Size = SMALL;
Index = 1;
PageSize = 30;
}
/// <summary> Gets or sets the index. </summary>
public int Index { get; set; }
/// <summary>
/// Gets or sets the picture links.
/// </summary>
/// <value>The picture links.</value>
public List<string> Pictures { get; private set; }
/// <summary>
/// Gets or sets the size.
/// </summary>
/// <value>The size.</value>
public int Size { get; set; }
private List<SelectListItem> validSizes = null;
/// <summary>
/// Gets the valid sizes.
/// </summary>
/// <value>The valid sizes.</value>
public IEnumerable<SelectListItem> ValidSizes
{
get {
if (validSizes != null)
return validSizes;
validSizes = new List<SelectListItem>
{
new SelectListItem(){Text = "Small", Value = SMALL.ToString()},
new SelectListItem(){Text = "Middle", Value = MIDDLE.ToString()},
new SelectListItem(){Text = "Big", Value = BIG.ToString()}
};
return validSizes;
}
}
}
EDIT2:
<div id="pager_left">
<%= Html.ActionLink("Prev", "Prev", Model)%>
</div></td>
That's the Action Link that causes the binding.
Use separate ViewModel for form input
Use IEnumerable instead of List
Use [Bind(Exclude="Pictures, ValidSizes")] on the action input parameter
Use private setters
Don't create form input elements for Pictures/ValidSizes if you don't need them
and so on.
Update:
You assign different ViewModel not to a view, but to the controller action that handles link click. And from your questions it seems that what you need is not "oneway" binding, but rather avoiding extra characters in URL - because, if your ValidSizes is IEnumerable it won't be altered, and anyway in your URL its data is wrong, won't cause update - so it's already "one-way" binding.
This is what I can find for your problem:
http://forums.asp.net/t/1328683.aspx
As for solution, I never use ActionLink helper myself, because it is a leaky abstraction and I don't like to fight with it. Simple html link tag is always much better.
<a href="<%= Html.BuildUrlFromExpression<>() %>" />
I actually use my own few-lines version of the BuildUrlFromExpression for this. Also see in the link above how you can pass parameters via anonymous object instead of Model (new { PageSize = Model.PageSize, index = Model.index }).

Resources