Why Vaadin TreeGrid loads the data two times after Scrolling? - vaadin

I have the following issue: When my Treegrid gets loaded for the first time, all the root data where correct added. But when i scroll drown in the TreeGrid, the data are picked up again and added to the Treegrid.
Does anyone know how to deactivate lazy loading in a Treegrid when scrolling?
Here is my Method which created the Treegrid
private Component createCategoriesTree() {
treeGrid.setHeight("100%");
treeGrid.addComponentHierarchyColumn(productCategory -> getProductCategoryName(productCategory)).setHeader("Kategorie").setSortable(false);
ProductCategory root = productCategoriesService.getRootCategory();
HierarchicalDataProvider dataProvider = new AbstractBackEndHierarchicalDataProvider<ProductCategory, Void>() {
#Override
public int getChildCount(HierarchicalQuery<ProductCategory, Void> query) {
if (query.getParent() == null) {
List<ProductCategory> list = productCategoriesService.findByParentId(root.getId());
return (int) list.size();
} else {
List<ProductCategory> list = productCategoriesService.findByParentId(query.getParent().getId());
return (int) list.size();
}
}
#Override
public boolean hasChildren(ProductCategory item) {
List<ProductCategory> list = productCategoriesService.findByParentId(item.getId());
if (list != null && list.size() > 0) {
return true;
} else {
return false;
}
}
#Override
protected Stream<ProductCategory> fetchChildrenFromBackEnd(HierarchicalQuery<ProductCategory, Void> query) {
if (query.getParent() == null) {
return productCategoriesService.findByParentId(root.getId()).stream();
} else {
return productCategoriesService.findByParentId(query.getParent().getId()).stream();
}
}
};
treeGrid.setDataProvider(dataProvider);
return treeGrid;
}

The issue was:
missing skip method like following method body:
#Override
protected Stream<ProductCategory> fetchChildrenFromBackEnd(HierarchicalQuery<ProductCategory, Void> query) {
if (query.getParent() == null) {
return productCategoriesService.findByParentIdOrderByCategoryNameAsc(root.getId()).stream().skip(query.getOffset()).limit(query.getLimit()); //THIS
} else {
return productCategoriesService.findByParentIdOrderByCategoryNameAsc(query.getParent().getId()).stream(); //THIS
}
}

Related

Full RelayCommand in F#?

I am new to F#. As a learning experiment, I am rewriting a C# application in pure F#. How can the "RelayCommand" , RelayCommand, of C# be written in F# ?
Any help is most appreciated.
TIA
As requested, this is the RelayCommand I've been using in C#. :( It seems overly complicated. (There must surely be a simpler one!).
public class RelayCommand<T> : ICommand
{
private readonly WeakAction<T> _execute;
private readonly WeakFunc<T, bool> _canExecute;
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = new WeakAction<T>(execute);
if (canExecute != null)
{
_canExecute = new WeakFunc<T, bool>(canExecute);
}
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
{
CommandManager.RequerySuggested += value;
}
}
remove
{
if (_canExecute != null)
{
CommandManager.RequerySuggested -= value;
}
}
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
if (_canExecute.IsStatic || _canExecute.IsAlive)
{
if (parameter == null && typeof(T).IsValueType)
{
return _canExecute.Execute(default(T));
}
if (parameter == null || parameter is T)
{
return (_canExecute.Execute((T)parameter));
}
}
return false;
}
public virtual void Execute(object parameter)
{
var val = parameter;
if (CanExecute(val)
&& _execute != null
&& (_execute.IsStatic || _execute.IsAlive))
{
if (val == null)
{
if (typeof(T).IsValueType)
{
_execute.Execute(default(T));
}
else
{
// ReSharper disable ExpressionIsAlwaysNull
_execute.Execute((T)val);
// ReSharper restore ExpressionIsAlwaysNull
}
}
else
{
_execute.Execute((T)val);
}
}
}
}
public class WeakFunc<TResult>
{
private Func<TResult> _staticFunc;
/// <summary>
/// Gets or sets the <see cref="MethodInfo" /> corresponding to this WeakFunc's
/// method passed in the constructor.
/// </summary>
protected MethodInfo Method
{
get;
set;
}
/// <summary>
/// Get a value indicating whether the WeakFunc is static or not.
/// </summary>
public bool IsStatic
{
get
{
return _staticFunc != null;
}
}
public virtual string MethodName
{
get
{
if (_staticFunc != null)
{
return _staticFunc.Method.Name;
}
return Method.Name;
}
}
protected WeakReference FuncReference
{
get;
set;
}
protected WeakReference Reference
{
get;
set;
}
protected WeakFunc()
{
}
public WeakFunc(Func<TResult> func)
: this(target: func?.Target, func: func)
{
}
public WeakFunc(object target, Func<TResult> func)
{
if (func.Method.IsStatic)
{
_staticFunc = func;
if (target != null)
{
// Keep a reference to the target to control the
// WeakAction's lifetime.
Reference = new WeakReference(target);
}
return;
}
Method = func.Method;
FuncReference = new WeakReference(func.Target);
Reference = new WeakReference(target);
}
public virtual bool IsAlive
{
get
{
if (_staticFunc == null
&& Reference == null)
{
return false;
}
if (_staticFunc != null)
{
if (Reference != null)
{
return Reference.IsAlive;
}
return true;
}
return Reference.IsAlive;
}
}
public object Target
{
get
{
if (Reference == null)
{
return null;
}
return Reference.Target;
}
}
protected object FuncTarget
{
get
{
if (FuncReference == null)
{
return null;
}
return FuncReference.Target;
}
}
public TResult Execute()
{
if (_staticFunc != null)
{
return _staticFunc();
}
var funcTarget = FuncTarget;
if (IsAlive)
{
if (Method != null
&& FuncReference != null
&& funcTarget != null)
{
return (TResult)Method.Invoke(funcTarget, null);
}
}
return default(TResult);
}
public void MarkForDeletion()
{
Reference = null;
FuncReference = null;
Method = null;
_staticFunc = null;
}
}
As a newbie to F#, how can this be implemented? How does F# deal with "WeakAction"?
Thank you.

Filter ListView with SearchView xamarin

I want to filter Listview by Searchview
I use the following Adapter for the filter and it works if I haven't made any new additions to the adapter
When I add a new item to Listview, the search stops completely until I restart the program after adding, modifying or deleting it
full code
adapter class
Do you want to achieve the result like following GIF?
If you want to add the item to the listview, based on your adapter, you should item in the adapter like following code.
public class TableItemAdapter : BaseAdapter<TableItem>, IFilterable
{
public List<TableItem> _originalData;
public List<TableItem> _items;
private readonly Activity _context;
public TableItemAdapter(Activity activity, IEnumerable<TableItem> tableitems)
{
_items = tableitems.ToList();
_context = activity;
Filter = new TableItemFilter(this);
}
//Add data to the `_items`, listview will be updated, if add data in the activity,
//there are two different lists, so listview will not update.
public void AddData(TableItem tableItem)
{
_items.Add(tableItem);
NotifyDataSetChanged();
}
public override TableItem this[int position]
{
get { return _items[position]; }
}
public Filter Filter { get; private set; }
public override int Count
{
get { return _items.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = _items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = convertView ?? _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
//view = _context.LayoutInflater.Inflate(Resource.Layout.TableItem, null);
view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;
return view;
}
public override void NotifyDataSetChanged()
{
// this.NotifyDataSetChanged();
base.NotifyDataSetChanged();
}
}
public class TableItemFilter :Filter
{
private readonly TableItemAdapter _adapter;
public TableItemFilter(TableItemAdapter adapter)
{
_adapter = adapter;
}
protected override FilterResults PerformFiltering(ICharSequence constraint)
{
var returnObj = new FilterResults();
var results = new List<TableItem>();
if (_adapter._originalData == null)
_adapter._originalData = _adapter._items;
if (constraint == null) return returnObj;
if (_adapter._originalData != null && _adapter._originalData.Any())
{
results.AddRange(
_adapter._originalData.Where(
item => item.SubHeading.ToLower().Contains(constraint.ToString()) | item.Heading.ToLower().Contains(constraint.ToString())));
}
returnObj.Values = FromArray(results.Select(r => r.ToJavaObject()).ToArray());
returnObj.Count = results.Count;
constraint.Dispose();
return returnObj;
}
protected override void PublishResults(ICharSequence constraint, FilterResults results)
{
using (var values = results.Values)
_adapter._items = values.ToArray<Java.Lang.Object>().Select(r => r.ToNetObject<TableItem>()).ToList();
_adapter.NotifyDataSetChanged();
// Don't do this and see GREF counts rising
constraint.Dispose();
results.Dispose();
}
}
public class JavaHolder : Java.Lang.Object
{
public readonly object Instance;
public JavaHolder(object instance)
{
Instance = instance;
}
}
public static class ObjectExtensions
{
public static TObject ToNetObject<TObject>(this Java.Lang.Object value)
{
if (value == null)
return default(TObject);
if (!(value is JavaHolder))
throw new InvalidOperationException("Unable to convert to .NET object. Only Java.Lang.Object created with .ToJavaObject() can be converted.");
TObject returnVal;
try { returnVal = (TObject)((JavaHolder)value).Instance; }
finally { value.Dispose(); }
return returnVal;
}
public static Java.Lang.Object ToJavaObject<TObject>(this TObject value)
{
if (Equals(value, default(TObject)) && !typeof(TObject).IsValueType)
return null;
var holder = new JavaHolder(value);
return holder;
}
}
}
Then in the activity, you add the data by adapter.
private void Button1_Click(object sender, System.EventArgs e)
{
tableItemAdapter.AddData(new TableItem() { Heading = "test1222", SubHeading = "sub Test" });
}
Here is my demo, you can download it.
https://github.com/851265601/Xamarin.Android_ListviewSelect/blob/master/XAListViewSearchDemo.zip

How to consume a TAB/Enter KeyPressed on the TextArea, and replace with focustraversal or enter key without using internal API?

I need to have a control which will wordwrap, add scrollbars, etc - but ignore the enter key and jump to the next control using tab/shift tab. I can't seem to get this right.
This is the control I have done, and it seems to just simply stay in the text area. (This was used from an old example online and it seems to work only if the textArea is in the same node as the rest).
public class TabAndEnterIgnoringTextArea extends TextArea {
final TextArea myTextArea = this;
public TabAndEnterIgnoringTextArea() {
this.setWrapText(true);
addEventFilter(KeyEvent.KEY_PRESSED, new TabAndEnterHandler());
}
private class TabAndEnterHandler implements EventHandler<KeyEvent> {
private KeyEvent recodedEvent;
#Override
public void handle(KeyEvent event) {
if (recodedEvent != null) {
recodedEvent = null;
return;
}
Parent parent = getParent();
if (parent != null) {
switch (event.getCode()) {
case ENTER:
if (event.isControlDown()) {
recodedEvent = recodeWithoutControlDown(event);
myTextArea.fireEvent(recodedEvent);
} else {
Event parentEvent = event.copyFor(parent, parent);
myTextArea.getParent().fireEvent(parentEvent);
}
event.consume();
break;
case TAB:
if (event.isControlDown()) {
recodedEvent = recodeWithoutControlDown(event);
myTextArea.fireEvent(recodedEvent);
} else if (event.isShiftDown()) {
ObservableList<Node> children = FXCollections.observableArrayList();
addAllDescendents(parent, children);
int idx = children.indexOf(myTextArea);
if (idx > 0) {
for (int i = idx - 1; i > 0; i--) {
if (children.get(i).isFocusTraversable()) {
children.get(i).requestFocus();
break;
}
}
}
} else {
ObservableList<Node> children = FXCollections.observableArrayList();
addAllDescendents(parent, children);
int idx = children.indexOf(myTextArea);
if (idx >= 0) {
for (int i = idx + 1; i < children.size(); i++) {
if (children.get(i).isFocusTraversable()) {
children.get(i).requestFocus();
break;
}
}
if (idx + 1 >= children.size()) {
for (int i = 0; i < idx; i++) {
if (children.get(i).isFocusTraversable()) {
children.get(i).requestFocus();
break;
}
}
}
}
}
event.consume();
break;
default:
break;
}
}
}
private void addAllDescendents(Parent parent, ObservableList<Node> nodes) {
for (Node node : parent.getChildrenUnmodifiable()) {
nodes.add(node);
if (node instanceof Parent)
addAllDescendents((Parent) node, nodes);
}
}
private KeyEvent recodeWithoutControlDown(KeyEvent event) {
return new KeyEvent(event.getEventType(), event.getCharacter(), event.getText(), event.getCode(),
event.isShiftDown(), false, event.isAltDown(), event.isMetaDown());
}
}
Once I land in my field, it won't leave with the keyboard. Any ideas? Also - I shouldn't assume that the next control is actually in the nodes within my parent, as the control may be part of another control where its the last control and the next one might be on the parent above.
Basically I want the next landable item in the scenegraph.
I am able to do it with internal API - but I know that is very discouraged.
public class TabAndEnterIgnoringTextArea extends TextArea {
final TextArea myTextArea = this;
public TabAndEnterIgnoringTextArea() {
addEventFilter(KeyEvent.KEY_PRESSED, new TabAndEnterHandler());
}
class TabAndEnterHandler implements EventHandler<KeyEvent> {
private KeyEvent recodedEvent;
#Override
public void handle(KeyEvent event) {
if (recodedEvent != null) {
recodedEvent = null;
return;
}
Parent parent = myTextArea.getParent();
Scene scene = parent.getScene();
while (scene == null){
parent = parent.getParent();
scene = parent.getScene();
}
SceneTraversalEngine engine = new SceneTraversalEngine(getScene());
if (parent != null) {
switch (event.getCode()) {
case ENTER:
if (event.isControlDown()) {
recodedEvent = recodeWithoutControlDown(event);
myTextArea.fireEvent(recodedEvent);
} else {
Event parentEvent = event.copyFor(parent, parent);
myTextArea.getParent().fireEvent(parentEvent);
}
event.consume();
break;
case TAB:
if(event.isShiftDown()){
engine.trav(myTextArea, Direction.PREVIOUS);
}else {
engine.trav(myTextArea, Direction.NEXT);
}
}
}
}
private KeyEvent recodeWithoutControlDown(KeyEvent event) {
return new KeyEvent(event.getEventType(), event.getCharacter(), event.getText(), event.getCode(),
event.isShiftDown(), false, event.isAltDown(), event.isMetaDown());
}
}
}
Thanks
I think I found a solution which will allow me to have this work as designed.
public class TabAndEnterIgnoringTextArea extends TextArea {
final TextArea myTextArea = this;
public TabAndEnterIgnoringTextArea() {
this.setWrapText(true);
addEventFilter(KeyEvent.KEY_PRESSED, new TabAndEnterHandler());
}
private class TabAndEnterHandler implements EventHandler<KeyEvent> {
#Override
public void handle(KeyEvent event) {
if(event.getCode() == KeyCode.TAB || event.getCode() == KeyCode.ENTER) {
event.consume();
if(event.getCode() == KeyCode.TAB){
selectNextNode(!event.isShiftDown());
}
}
}
private void selectNextNode(boolean forward){
List<Node> nodes = getAllNodes(myTextArea.getScene().getRoot());
int index = nodes.indexOf(myTextArea);
if(forward){
if(index < nodes.size() - 1) {
nodes.get(index + 1).requestFocus();
}else {
nodes.get(0).requestFocus();
}
}else {
if(index == 0) {
nodes.get(nodes.size() - 1).requestFocus();
}else {
nodes.get(index - 1).requestFocus();
}
}
}
private ArrayList<Node> getAllNodes(Parent root) {
ArrayList<Node> nodes = new ArrayList<Node>();
addAllDescendents(root, nodes);
return nodes;
}
private void addAllDescendents(Parent parent, ArrayList<Node> nodes) {
for (Node node : parent.getChildrenUnmodifiable()) {
if(node.isFocusTraversable()){
nodes.add(node);
}
if (node instanceof Parent)
addAllDescendents((Parent)node, nodes);
}
}
}
}
If you see anything wrong with this approach I would appreciate it, but it seems to work for my purposes.

MVVMCROSS Binding TimeSyncProblem

I've got a special problem with binding data to an itemsource of an mvxtablieviewsource.
I'm trying to generate a list of favorites, which are generated in the core by clicking on a different tablview.
Normally I get the databinding working like this: (Just basic structure)
controller:
var source = new MySource(TableView);
this.AddBindings(new Dictionary<object, string>
{
{source, "ItemsSource Favs"}
});
Source:
private List<FavModel> _favs;
public override IEnumerable ItemsSource
{
get { return _favs; }
set
{
_favs = (List<FavModel>)value;
ReloadTableData();
}
}
protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
{
var cell = new AdFavCell();
cell.TextLabel.Text = ((FavModel)item).Display;
return cell;
}
Normally it works really great but no in this case where i generate the data by reacting on users touch, I've got this strange failure;
When I set a breakpoint in the setter of the ItemsSource, and wait for a while then it works correctly.
When I run without a breakpoint the tableview keeps empty.
I also figured out that if I insert a manually pause in the setter then it works too:
Setter with pause:
public override IEnumerable ItemsSource
{
get { return _mydata; }
set
{
_favs = (List<FavModel>)value;
ReloadTableData();
Task.Delay(1000).Wait();
}
}
I also tried to do a delaybinding, but it didn't work.
Have anyone an idea where the problem is?
Edit:
Here some additional Information:
How the Data is generated:
I've got a tableview with content and depending on a longclick on a cell, I create a popumenu where you can add your favorites.
Detecting the longclick:
protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
{
MvxTableViewCell cell = null;
if (item is SoccerEventListModel)
{
cell = tableView.DequeueReusableCell(this.CellIdentifier) as SoccerEvent;
if (cell == null)
{
cell = new SoccerEvent((SoccerEventListModel)item);
cell.AddGestureRecognizer(new UILongPressGestureRecognizer((e) =>
{
if (e.State == UIGestureRecognizerState.Began)
{
var command = ItemLongClickCommand;
if (command != null)
command.Execute(item);
}
}));
return cell;
}
}
}
Binding the Longclick to the core:
EventListViewModel.EventFavViewCallbackEvent += EventListViewModel_EventFavViewCallbackEvent;
void EventListViewModel_EventFavViewCallbackEvent(EventModel e)
{
var StoreFav = new EventFavoritesView { ViewModel = new EventFavoritesViewModel { ID = e.ID } };
View.Add(StoreFav.View);
}
Depending on the ID of the cell, it creates the list of the favorites by sending a request to our server.
Update:
private long _id;
public long ID
{
get { return _id; }
set { _id = value; RaisePropertyChanged(() => ID); Update(); }
}
When the data is received a RaisePropertyChanged() should make the view to reload its content.
private List<FavModel> _favs;
public List<FavModel> Favs
{
get { return _favs; }
set { _favs = value; RaisePropertyChanged(() => Favs); }
}
ViewModel:
public class EventFavoritesViewModel : MvxViewModel
{
private readonly EventFavoritesService _eventFavoriteService;
private readonly UserFavoritesService _userFavoriteService;
private long _id;
public long ID
{
get { return _id; }
set { _id = value; RaisePropertyChanged(() => ID); Update(); }
}
private string _title;
public string Title
{
get { return _title; }
set { _title = value; RaisePropertyChanged(() => Title); }
}
private List<FavModel> _favs;
public List<FavModel> Favs
{
get { return _favs; }
set { _favs = value; RaisePropertyChanged(() => Favs); }
}
private MvxCommand<FavModel> _itemSelectedCommand;
public System.Windows.Input.ICommand ItemSelectedCommand
{
get
{
_itemSelectedCommand = _itemSelectedCommand ?? new MvxCommand<FavModel>(ToggleFav);
return _itemSelectedCommand;
}
}
public void Init(long eventID)
{
MvxTrace.Trace("We get the details", Logger.Errorlevel.Debug);
ID = eventID;
}
public EventFavoritesViewModel()
{
_eventFavoriteService = new EventFavoritesService(UpdateEventFav);
_userFavoriteService = new UserFavoritesService(UpdateUserFav);
}
private void UpdateUserFav(Fav[] favlist)
{
MvxMessenger.Publish(new UserFavUpdateMessage(this, favlist));
}
private void Update()
{
Favs = _eventFavoriteService.GetFavforEvent(ID).MapToFavs();
}
private void UpdateEventFav(Fav[] favlist)
{
Favs = favlist.MapToFavs();
}
private void ToggleFav(FavModel item)
{
MvxTrace.Trace("Got Item: " + item.Display);
item.NewSubscription = !item.NewSubscription;
}
private IMvxMessenger MvxMessenger
{
get
{
return Mvx.Resolve<IMvxMessenger>();
}
}
public void SaveFavs()
{
foreach (var fav in Favs)
{
if (fav.AlreadySubscribed != fav.NewSubscription)
{
if (fav.NewSubscription)
_userFavoriteService.PutToUserFavorites(fav.MapToFav());
else
_userFavoriteService.DeleteFromUserFavorites(fav.MapToFav());
}
}
}
}
I hope this is enough information, otherwise just tell me.:-)
Thanks for any help.

Create a custom Spinner

I am trying to customize the MvxSpinner to add some additional controls, here is my code:
public class ChamSpinner : LinearLayout
{
public Spinner Spinner{ get; private set; }
public EventHandler<AdapterView.ItemSelectedEventArgs> ItemSelected;
public ChamSpinner (Context context, IAttributeSet attrs) : this (context, attrs, new ChamSpinnerAdapter (context))
{
}
public ChamSpinner (Context context, IAttributeSet attrs, IMvxAdapter adapter) : base (context, attrs)
{
((Activity)Context).LayoutInflater.Inflate (Resource.Layout.ChamSpinnerLayout, this);
Spinner = FindViewById<Spinner> (Resource.Id.ChamSpinnerSpinner);
int itemTemplateId = MvxAttributeHelpers.ReadListItemTemplateId (context, attrs);
int dropDownItemTemplateId = MvxAttributeHelpers.ReadDropDownListItemTemplateId (context, attrs);
adapter.ItemTemplateId = itemTemplateId;
adapter.DropDownItemTemplateId = dropDownItemTemplateId;
Adapter = adapter;
SetupHandleItemSelected ();
}
public new IMvxAdapter Adapter
{
get { return Spinner.Adapter as IMvxAdapter; }
set
{
var existing = Adapter;
if (existing == value)
return;
if (existing != null && value != null)
{
value.ItemsSource = existing.ItemsSource;
value.ItemTemplateId = existing.ItemTemplateId;
}
Spinner.Adapter = value;
}
}
[MvxSetToNullAfterBinding]
public IEnumerable ItemsSource
{
get
{
return Adapter.ItemsSource;
}
set
{
Adapter.ItemsSource = value;
}
}
public int ItemTemplateId
{
get { return Adapter.ItemTemplateId; }
set { Adapter.ItemTemplateId = value; }
}
public int DropDownItemTemplateId
{
get { return Adapter.DropDownItemTemplateId; }
set { Adapter.DropDownItemTemplateId = value; }
}
public ICommand HandleItemSelected { get; set; }
private void SetupHandleItemSelected ()
{
Spinner.ItemSelected += (sender, args) =>
{
var position = args.Position;
HandleSelected (position);
if (ItemSelected != null)
ItemSelected (sender, args);
};
}
protected virtual void HandleSelected (int position)
{
var item = Adapter.GetRawItem (position);
if (this.HandleItemSelected == null
|| item == null
|| !this.HandleItemSelected.CanExecute (item))
return;
this.HandleItemSelected.Execute (item);
}
}
And I am using it like this:
<cross.android.ChamSpinner
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxDropDownItemTemplate="#layout/myspinneritemdropdown"
local:MvxItemTemplate="#layout/myspinneritem"
local:MvxBind="ItemsSource MyItemsSource; SelectedItem MyItem; Mode TwoWay" />
The spinner is always empty, I tried to add a custom binding on ItemsSource property but the result stilll the same.
How can I do to show my items in my spinner?
Thank you in advance.
I think using BindingInflate instead of Inflate should fix it or even points you in the right direction. https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Droid/BindingContext/IMvxAndroidBindingContext.cs
((IMvxBindingContextOwner)Context).BindingInflate(Resource.Layout.ChamSpinnerLayout, this);
I found this error in my log
MvxBind:Error: 32,12 View type not found - cross.android.ChamSpinner
My custom control is in another assembly so I added it to MvvmCross View assemblies is my Setup class like this
protected override IList<Assembly> AndroidViewAssemblies
{
get
{
var assemblies = base.AndroidViewAssemblies;
assemblies.Add(typeof(ChamSpinner).Assembly);
return assemblies;
}
}
Thank you Stuart for your advices and for your great Framework.

Resources