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.
Related
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)
);
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);
When you create a SelectList you can optionally pass in the SelectedValue property for which the documentation says
// selectedValue:
// The selected value. Used to match the Selected property of the corresponding
// System.Web.Mvc.SelectListItem.
However, if you pass it a value object which is not contained in the list of items, it still sets the selected value. Try this:
using System.Web.Mvc;
class SomeItem
{
public int id { get; set; }
public string text { get; set; }
}
class CreateSelectList
{
public static SelectList CreateSelectList()
{
List<SomeItem> items = new List<SomeItem>();
for (int i = 0; i < 3; i++)
{
items.Add(new SomeItem() { id = i, text = i.ToString() });
}
// 5 is not in the list of items yet the property SelectedValue does = 5
return new SelectList(items, "id", "text", 5);
}
}
My questions are:
Since I want to lazily set my selected value only if it exists, I just want to pass in a value and have it ignored when it does not exist in the list, but how? (is this a bug or a design feature), or
If you create a SelectList without the SelectedValue, after you have constructed it, how can you set the SelectedValue (again when it exists in the list) ?
If your code is near to your real scenario, you could use something like this
// check if there is any element with id = 5
if (items.Any(i => i.id == 5))
{
// there is an element with id = 5 so I set the selected value
return new SelectList(items, "id", "text", 5);
}
else
{
// there is no element with id = 5 so I don't set the selected value
return new SelectList(items, "id", "text");
}
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.
This has totally puzzled me.
Here's my View:
#Html.DropDownListFor(model => model.ScoreDescription,
Model.RatingOptions,
"--",
new { #id = clientId })
And the model:
public decimal? Score { get; set; }
public SelectList RatingOptions
{
get
{
var options = new List<SelectListItem>();
for (var i = 1; i <= 5; i++)
{
options.Add(new SelectListItem
{
Selected = Score.HasValue && Score.Value == Convert.ToDecimal(i),
Text = ((decimal)i).ToRatingDescription(ScoreFactorType),
Value = i.ToString()
});
}
var selectList = new SelectList(options, "Value", "Text");
// At this point, "options" has an item with "Selected" to true.
// Also, the underlying "MultiSelectList" also has it.
// Yet selectList.SelectedValue is null. WTF?
return selectList;
}
}
As the comments suggest, i can't get the selected value to happen.
Is it something to do with the fact i'm using a nullable decimal ? After that loop, options is correct in that it has exactly 1 item with select to true, so it seems i'm doing the right thing.
Now, if i use a different SelectList overload:
var selectedValue = Score.HasValue ? Score.Value.ToString("0") : string.Empty;
var selectList = new SelectList(options, "Value", "Text", selectedValue);
It works. Why? At first i thought it might be a LINQ-trick (e.g deferred execution), but i tried forcing a .ToList() and there is no difference.
It's like setting the Selected property as you create the SelectListItem has no effect, and you have you set it at the end using the SelectList ctor parameter.
Can anyone shed some light on this?
If you look at the implementation of the SelectList class it never actually uses the fact that you are passing a SelectListItem. It works with an IEnumerable. So the Selected property of a SelectListItem is not used. Personally I prefer setting the selected value of a dropdown by setting the value of the corresponding property that you are binding the ddl to.
Example:
public int? Score { get; set; }
public SelectList RatingOptions
{
get
{
var options = Enumerable.Range(1, 5).Select(i => new SelectListItem
{
Text = ((decimal)i).ToRatingDescription(ScoreFactorType),
Value = ((decimal)i).ToString()
});
return new SelectList(options, "Value", "Text");
}
}
and then in the controller action simply set the Score property to the necessary value and in the view use this Score property to bind to:
#Html.DropDownListFor(
model => model.Score,
Model.RatingOptions,
"--",
new { #id = clientId }
)