9

我只是想知道 ExpandableListViews 的功能或类似的功能是否潜伏在 Mvvmmcross 框架中,或者这种类型的控件是否不适用于多平台要求。在 http://deapsquatter.blogspot.com/2013/02/mvvmcrossdeapextensions.html找到的功能很酷,但不确定展开/折叠功能是否可用。

任何指针/示例代码将不胜感激

4

2 回答 2

6

这就是它(我把它放在 Deepsqautter 的代码中)。整理完代码后,我会把它放在方便的地方,或者它可能是 mvvmcross 本身的有用补充......

风景:

public class BindableExpandableListView : ExpandableListView
    {
        public BindableExpandableListView(Context context, IAttributeSet attrs)
            : this(context, attrs, new BindableExpandableListAdapter(context))
        {
        }
    public BindableExpandableListView(Context context, IAttributeSet attrs, BindableExpandableListAdapter adapter)
        : base(context, attrs)
    {
        var groupTemplateId = MvxAttributeHelpers.ReadAttributeValue(context, attrs,
                                                                           MvxAndroidBindingResource.Instance
                                                                            .ListViewStylableGroupId,
                                                                           AndroidBindingResource.Instance
                                                                           .BindableListGroupItemTemplateId);
 
        var itemTemplateId = MvxAttributeHelpers.ReadListItemTemplateId(context, attrs);
        SetAdapter(adapter);
        adapter.GroupTemplateId = groupTemplateId;
        adapter.ItemTemplateId = itemTemplateId;
    }

    // An expandableListView has ExpandableListAdapter as propertyname, but Adapter still exists but is always null.
    protected BindableExpandableListAdapter ThisAdapter { get { return ExpandableListAdapter as BindableExpandableListAdapter; } }

    

    private IEnumerable _itemsSource;
    [MvxSetToNullAfterBinding]
    public virtual IEnumerable ItemsSource
    {
        get { return ThisAdapter.ItemsSource; }
        set { ThisAdapter.ItemsSource = value; }
    }

    public int ItemTemplateId
    {
        get { return ThisAdapter.ItemTemplateId; }
        set { ThisAdapter.ItemTemplateId = value; }
    }

    private ICommand _itemClick;
    public new ICommand ItemClick
    {
        get { return _itemClick; }
        set { _itemClick = value; if (_itemClick != null) EnsureItemClickOverloaded(); }
    }

    public ICommand GroupClick { get; set; }

    private bool _itemClickOverloaded = false;
    private void EnsureItemClickOverloaded()
    {
        if (_itemClickOverloaded)
            return;

        _itemClickOverloaded = true;
        base.ChildClick += (sender, args) => ExecuteCommandOnItem(this.ItemClick, args.GroupPosition, args.ChildPosition);
    }


    protected virtual void ExecuteCommandOnItem(ICommand command, int groupPosition, int position)
    {
        if (command == null)
            return;

        var item = ThisAdapter.GetRawItem(groupPosition, position);
        if (item == null)
            return;

        if (!command.CanExecute(item))
            return;

        command.Execute(item);
    }
}

和适配器

public class BindableExpandableListAdapter : MvxAdapter, IExpandableListAdapter
    {
    private IList _itemsSource;

    public BindableExpandableListAdapter(Context context)
        : base(context)
    {
        
    }

    int groupTemplateId;
    public int GroupTemplateId
    {
        get { return groupTemplateId; }
        set
        {
            if (groupTemplateId == value)
                return;
            groupTemplateId = value;

            // since the template has changed then let's force the list to redisplay by firing NotifyDataSetChanged()
            if (ItemsSource != null)
                NotifyDataSetChanged();
        }
    }

    protected override void SetItemsSource(System.Collections.IEnumerable value)
    {
        Mvx.Trace("Setting itemssource");
        if (_itemsSource == value)
            return;
        var existingObservable = _itemsSource as INotifyCollectionChanged;
        if (existingObservable != null)
            existingObservable.CollectionChanged -= OnItemsSourceCollectionChanged;

        _itemsSource = value as IList;

        var newObservable = _itemsSource as INotifyCollectionChanged;
        if (newObservable != null)
            newObservable.CollectionChanged += OnItemsSourceCollectionChanged;

        if (value != null)
        {
            // dit weggehaald FlattenAndSetSource(value);
        }
        else
            base.SetItemsSource(null);
    }



    public int GroupCount { get { return (_itemsSource != null ? _itemsSource.Count : 0); } }
    public void OnGroupExpanded(int groupPosition)
    {
        // do nothing
    }

    public void OnGroupCollapsed(int groupPosition)
    {
        // do nothing
    }

    public bool IsChildSelectable(int groupPosition, int childPosition)
    {
        return true;
    }

    public View GetGroupView(int groupPosition, bool isExpanded, View convertView, ViewGroup parent)
    {
        var item = _itemsSource[groupPosition];
        return base.GetBindableView(convertView, item, GroupTemplateId);
    }

    public long GetGroupId(int groupPosition)
    {
        return groupPosition;
    }

    public Java.Lang.Object GetGroup(int groupPosition)
    {
        return null;
    }

    public long GetCombinedGroupId(long groupId)
    {
        return groupId;
    }

    public long GetCombinedChildId(long groupId, long childId)
    {
        return childId;
    }

    public object GetRawItem(int groupPosition, int position)
    {
        return ((_itemsSource[groupPosition]) as IEnumerable).Cast<object>().ToList()[position];
    }

    public View GetChildView(int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
    {
        var sublist = ((_itemsSource[groupPosition]) as IEnumerable).Cast<object>().ToList();

        var item = sublist[childPosition];
        return base.GetBindableView(convertView, item, ItemTemplateId);
    }

    public int GetChildrenCount(int groupPosition)
    {
        return ((_itemsSource[groupPosition]) as IEnumerable).Cast<object>().ToList().Count();
    }

    public long GetChildId(int groupPosition, int childPosition)
    {
        return childPosition;
    }

    public Java.Lang.Object GetChild(int groupPosition, int childPosition)
    {
        return null;
    }

    //public object GetRawItem
}

以及示例 XAML 代码:

<DeapExtensions.Binding.Droid.Views.BindableExpandableListView
    android:minWidth="25px"
    android:minHeight="25px"
    android:id="@+id/toclist"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    local:MvxBind="ItemsSource Chapters; ItemClick ShowCommand"
    local:MvxItemTemplate="@layout/indextocsectionlistitem"
    local:GroupItemTemplate="@layout/indextocitem"
    android:background="@android:color/white" />

然后甚至是一些数据示例(伪代码):

public class SubItem {
  public String Name {get; set;}
}

// this is the special part: a chapter does not CONTAIN a sublist, but IS a list of subitems.
public class Chapter : List<Subitem> {
  public String Name {get; set;}
}

// en some usage code
var chapters = new List<Chapter>();
var chapter = new Chapter(){Name = "chap 1"};
chapter.Add(new SubItem(){Name = " 1"});
chapter.Add(new SubItem(){Name = "item 2"});
chapters.Add(chap);

这是我的 MvxBindingAttributes.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="MvxBinding">
    <attr name="MvxBind" format="string"/>
    <attr name="MvxLang" format="string"/>
  </declare-styleable>
  <declare-styleable name="MvxControl">
    <attr name="MvxTemplate" format="string"/>
  </declare-styleable>
  <declare-styleable name="MvxListView">
    <attr name="MvxItemTemplate" format="string"/>
    <attr name="MvxDropDownItemTemplate" format="string"/>
    <attr name="GroupItemTemplate" format="string"/>

  </declare-styleable>
  <item type="id" name="MvxBindingTagUnique"/>
  <declare-styleable name="MvxImageView">
    <attr name="MvxSource" format="string"/>
  </declare-styleable>
</resources>

BTW:我在 MvvmCross 中只剩下一个项目,其余的已转换为 Xamarin.Forms 甚至远离 Xamarin。所以代码不再更新。

于 2013-07-18T21:49:28.930 回答
1

据我所知,以前没有人这样做过

但是您可以相当简单地将现有的 Android 控件转换为绑定控件 - 您已经在 @deapsquatter 的 repo 中看到了它是如何完成的。

要转换 ExpandableListView,我会一步一步来。

  1. 首先获取要使用的结构中的数据
  2. 然后手工制作一个非绑定的 UI - 只是快速原型设计
  3. 最后以@deapsquatter 的样本并尝试应用相同的原则。

当/如果您遇到特定问题时,您可以随时回到这里询问这些问题。但是,首先将 1 和 2 放在适当的位置,那么您将有一些可靠的问题要问。

希望有帮助。

于 2013-02-21T19:31:30.950 回答