Mvvmcross MVXView within a ViewController binding - ios

I am trying to bind a property of an MvxView that is contained in a View, but the binding doesn't seem to work.
The MvxView :
[Register("UIWeek")]
public partial class UIWeek : MvxView
Picture of the View Containing UIWeek
The property I am trying to bind in UIWeek:
public DateTime SelectedDate
{
get
{
return _selectedDate;
}
set
{
if (_selectedDate != value)
{
DateTime oldSelectedDate = _selectedDate;
_selectedDate = value;
_dispatcher.RequestMainThreadAction(() => RaiseSelectedDateChanged(_selectedDate, oldSelectedDate));
}
}
}
The binding in the view controller :
set.Bind(InvoiceDateWeekView).For(v => v.SelectedDate).To(vm => vm.InvoiceDate);

Related

How to set a selected value of kendo dropdown list from a controller based on a locale?

I have a Kendo.DropDownList that will display cultures.
When first loading the DropDown, I want to set its default, selected value to a current culture.
This is dropdown:
#(Html.Kendo().DropDownList()
.Name("culture")
.DataValueField("Value")
.DataTextField("DisplayText")
.DataSource(dataSource =>
{
dataSource.Read(read =>
{
read.Action("PopulateCultures", "CultureSelector");
});
})
.Events(events =>
{
events.Select("onCultureChange");
})
.SelectedIndex(0)
)
This is where I'm populating it:
public ActionResult PopulateCultures()
{
CultureModel cm = new CultureModel();
string uCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.ToString();
List<Culture> cultures = null;
cultures = cm.PopulateCulture();
if (Session["SiteUICulture"] != null) uCulture = Session["SiteUICulture"].ToString();
try
{
//Here I need to set default/selected value to a culture
cultures = cm.PopulateCulture();
}
catch (Exception e)
{
}
return Json(cultures, JsonRequestBehavior.AllowGet);
}
The Model:
public class CultureModel
{
public string CurrentName { get; set; }
public List<Culture> AvailableCultures { get; set; }
public List<Culture> PopulateCulture()
{
ClientServer iClient = new ClientServer();
AvailableCultures = iClient.GetCultures(applicationName).ToList();
return AvailableCultures;
}
}
How can I do that?
Try the following steps:-
The model bound to your view should have a property for the selected culture value. You can alternatively use ViewBag if you do not want to add a property to your Model.
The controller action corresponding to the view, should assign this a value to this property.
On the view set this model value to the drop down list
For Example:
Available Cultures bound to your dropdown are:-
[{ Id=1, Name=English-US}, { Id=2, Name=English-UK}]
If the name of the property you added is SelectedCulture
Your controller would set it to an available value like SelectedCulture = 1
Your view would set the value in the dropdown
#(Html.Kendo().DropDownList()
.Name("culture")
.DataValueField("Value")
.DataTextField("DisplayText")
.DataSource(dataSource =>
{
dataSource.Read(read =>
{
read.Action("PopulateCultures", "CultureSelector");
});
})
.Events(events =>
{
events.Select("onCultureChange");
})
.Value(Model.SelectedCulture)
);

MVC EditorFor to Title Case

How do you convert input value to title case in EditorFor? I know doing
#Html.EditorFor(model, new { htmlAttributes = new { #style = "text-transform:uppercase" } })
will only change the client side so I need to change it manually on server side.
I tried adding the class text-capitalize but seems no luck.
Thanks in advance.
Here are explanations to use either title case or sentence case for viewmodel's string properties which bound to EditorFor:
1) If you want to use title case, you can set it inside getter part with ToTitleCase method (change CurrentCulture to InvariantCulture depending on your requirements), as in example below:
private string _titleCase;
private System.Globalization.CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture;
public string TitleCaseProperty
{
get
{
if (string.IsNullOrEmpty(_titleCase))
{
return _value;
}
else
{
return culture.TextInfo.ToTitleCase(_titleCase.ToLower());
}
}
set
{
_titleCase = value;
}
}
View usage
#Html.EditorFor(model => model.TitleCaseProperty, ...)
2) If you want sentence case instead, use regular expression to find out sequences (referenced from this similar issue) and do similar way to getter part like above:
private string _sentenceCase;
private Regex rgx = new Regex(#"(^[a-z])|[?!.:,;]\s+(.)", RegexOptions.ExplicitCapture);
public string SentenceCaseProperty
{
get
{
if (string.IsNullOrEmpty(_sentenceCase))
{
return _value;
}
else
{
return rgx.Replace(_sentenceCase.ToLower(), s => s.Value.ToUpper());
}
}
set
{
_sentenceCase = value;
}
}
View usage
#Html.EditorFor(model => model.SentenceCaseProperty, ...)
Live example: .NET Fiddle Demo
I would recommend performing this conversion at the getter of this property using .ToUpper()
get {
if (string.IsNullOrEmpty(_value))
{
return _value;
}
return _value.ToUpper();
}
easier method
#Html.TextBoxFor(model.FieldName, new { #class = "uppercase" })
css:
.uppercase { text-transform:uppercase }

mvxspinner not change display value in my viewmodel

I have a button to change my mvxspinner, but in my view model I can't change the value displayed in my mvxspinner. For Example :
I have the mvxspinner and button in a layout :
<MvxSpinner
style="#style/SpinnerField.Filter"
android:id="#+id/filter_listacliente_spinner_bairro"
local:MvxBind="ItemsSource ListaBairro;SelectedItem FiltroBairro;"
local:MvxItemTemplate="#layout/filter_spinner_bairro"
local:MvxDropDownItemTemplate="#layout/filter_item_spinner_bairro" />
<Button
android:id="#+id/filter_listacliente_btlimpar"
android:theme="#style/DefaultButton"
local:MvxBind="Click LimparFiltros"
style="#style/DefaultButtonFilter"/>
In my ICommand, I tried changing my value to "Estado" and ID to "-1":
public ICommand LimparFiltros
{
get
{
return new MvxCommand(() =>
{
FiltroEstado = new EstadoDto { IdEstado = -1, Descricao = "Estado" };
});
}
}
My SelectedItem :
var _filtroEstado = new EstadoDto();
public EstadoDto FiltroEstado
{
get { return _filtroEstado; }
set
{
_filtroEstado = value;
RaisePropertyChanged(() => FiltroEstado);
}
}
Result for this: Nothing change in my display :(.
Expected result: My display have a description "Estado" selected
You are addressing the backing field _filtroEstado which will not cause the RaisePropertyChanged in your FiltroEstado property set to fire an INotifyPropertyChanged event. So the view with never get notified of the change.
return new MvxCommand(() =>
{
_filtroEstado = new EstadoDto { IdEstado = -1, Descricao = "Estado" };
});
Additionally, the reference for the SelectedItem needs to come form the bound ItemsSource list. Therefore, you could do something like:
return new MvxCommand(() =>
{
FiltroBairro = ListaBairro.FirstOrDefault(x => x.IdEstado == -1);
});
You're setting your private variable, _filtroEstado, inside LimparFiltros. As a result, the set on the public FiltroEstado property isn't firing, and neither is the RaisePropertyChanged.

An item with the same key has already been added when loading Kendo MVC Grid

I am trying to populate a Kendo mvcGrid and I keep getting the error An item with the same key has already been added.
I have seen elsewhere that duplicate model properties is the likeliest source of the problem but I have no duplicate properties in my model. I've even simplified everything to just a basic mock up to eliminate as many possible variables as possible..and I cant get the grid to load data.
I've tried it as a Html.Partial where its not loaded initially because of a empty model and then loading it through jquery...Ive tried with passing in am empty model so that the grid will load initially without data and then doing a datasource refresh...no luck there either. Basically as soon as I try to add content to the grid with a populated model I get the error and no data is loaded.
Been fighting this issue for 2 days now and had no luck. Ill post my code here maybe someone else can see what I'm missing.
One variable that cant change is the grid resides on a partial view with a model different from its parent view.
in the parent view I have tried both
<div id ="columnkgrid">#{Html.RenderPartial("Columns", new TestFieldIssue.Models.FieldListModel());}</div>
and
<div id="columnkgrid">#Html.Partial("Columns", new TestFieldIssue.Models.FieldListModel())</div>
either way will succeed in posting a grid with no data..it has no data yet because its populated by the selection of a value in a dropdown list.
so as to not over complicate the sample I've just set a hard coded value in the jquery function I have been using to refresh the grid.
function loadgrid() {
var grid = $("#grid").data("kendoGrid");
var val = 1;
grid.dataSource.read({ table_pk: val });
grid.refresh();
}
the grid code in the partial once again kept it simple without any bells and whistles just to test.
#(Html.Kendo().Grid(Model.fields)
.DataSource(data => data
.Ajax()
.Model(model => model.Id(m => m.field_pk))
.Read(r => r.Action("Columns","Home"))
)
.Name("grid")
.Columns(c =>
{
c.Bound(m => m.field_name).Title("Field Name").Width(100);
})
)
and the controller methods loading some mock data
public ActionResult Columns(int? table_pk)
{
FieldListModel model;
if (table_pk == null)
{
model = GetEmptyColumns();
}
else
{
model = GetColumns();
}
return PartialView("Columns", model);
}
public FieldListModel GetColumns()
{
FieldListModel model = new FieldListModel();
model.fields = new List<FieldModel>();
model.fields.Add(new FieldModel { field_name = "field1", field_pk = 1 });
model.fields.Add(new FieldModel { field_name = "field2", field_pk = 2 });
model.fields.Add(new FieldModel { field_name = "field3", field_pk = 3 });
return model;
}
public FieldListModel GetEmptyColumns()
{
FieldListModel model = new FieldListModel();
model.fields = new List<FieldModel>();
model.fields.Add(new FieldModel { field_name = "", field_pk = 0 });
return model;
}
and a very simple Model
public class FieldListModel
{
public List<FieldModel> fields { get; set; }
}
public class FieldModel
{
public int field_pk { get; set; }
public string field_name { get; set; }
}
I made few changes to run your code (correct version of Kendo and JQuery). May be those related to setup at my machine. I was able to reproduce the problem.
Then I changed the action code and was able to see the values populated in Grid:
public ActionResult Columns(int? table_pk, [DataSourceRequest] DataSourceRequest request)
{
FieldListModel model;
if (table_pk == null)
{
model = GetEmptyColumns();
}
else
{
model = GetColumns();
}
return Json(model.fields.ToDataSourceResult(request));
}
The change is accepting an additional parameter in action method of type DataSourceRequest. The Kendo grid wraps request in this object to specify sorting and paging information. The grid itself gets updated with data wrapped under DataSourceRequest object (note in return statement). More information here.

Bound CheckboxElement does not update its UI correctly

To have a bindable checkbox-list in iOS with MvvmCross, I created a view-class that holds a checkbox element, that is bound to the item viewmodel:
public class CheckListItemView : BaseView
{
public CheckListItemView()
{
var set = this.CreateBindingSet<CheckListItemView, CheckListItemViewModel>();
var item = new CheckboxElement();
set.Bind(item).For(v => v.Value).To(vm => vm.IsChecked).TwoWay();
set.Apply();
this.CheckboxElement = item;
}
public new CheckListItemViewModel ViewModel
{
get { return base.ViewModel.As<CheckListItemViewModel>(); }
set { base.ViewModel = value; }
}
public Element CheckboxElement { get; set; }
}
Unfortunately, in this case the binding is not too reliable: I have a button that checks all items checked and one that un-checks all boxes.
foreach (var checkListItemViewModel in checkList)
{
checkListItemViewModel.IsChecked = value;
}
If I keep pressing those two buttons for a time, at some point the UI does not update the checked state correctly. The values in the background are correct, though.

Resources