public override View GetView(int position, View convertView, ViewGroup parent) { T item = this[position]; if (convertView == null) { convertView = CreateView.Invoke(parent); } var dataContextProperty = convertView.GetType().GetProperties().FirstOrDefault(i => i.Name.Equals("DataContext")); if (dataContextProperty != null) { dataContextProperty.SetValue(convertView, item); } return(convertView); }
public override View GetView(int position, View convertView, ViewGroup parent) { // The convertView is the previous View at that position (if there is one). // So that means if something was inserted at the top, the convertView would be off by one index. // We could theoretically assign the new data context on each one, but that means there would // be O(N) changes to the data context of each. // Alternatively, we can cache mappings between the item and its convertView, and return the corresponding // view if it exists, and otherwise create and map it. That should be O(1). // However, the convertView is also used for recycling views when scrolling through long lists... // So theoretically, as we scroll down, the item's view at the top would end up appearing for an item further down, // which we wouldn't return, and instead we would create a new one, and the top item's view would lose its reference. // Best design would probably have a ViewWithDataContext, and then assign DataContext on them. // We could also support options for keeping all views loaded. if (CreateView == null) { throw new NullReferenceException("CreateView function cannot be null."); } var dataItem = this[position]; var cachedView = GetCachedView(dataItem); if (cachedView != null) { return(cachedView); } var newView = CreateView.Invoke(parent, dataItem); CacheCreatedView(dataItem, newView); return(newView); }
protected void InvokeCreateViewEvent(object derivedSender, ViewModelEventArgs e) { CreateView?.Invoke(derivedSender, e); }