mvxlistview点击项目

时间:2014-04-04 13:27:30

标签: xamarin.android xamarin mvvmcross mvxbind

我目前正在使用MvvmCross为Android创建应用。该应用程序的一部分需要一个MvxListView,其中每个项目有2个TextViews。默认情况下隐藏其中一个TextView。我正在寻求实现类似手风琴的功能,点击第一个TextView将显示/隐藏其他TextView。

我目前使用MvvmCross可见性插件获得大部分内容,但是click事件绑定到MvxListView而不是其中的TextView。我目前的工作方式如下:

FirstViewModel:
public class FirstViewModel
    : MvxViewModel
{
    public FirstViewModel(IListService listService)
    {
        Interests = new ObservableCollection<Interest>();
        List<Interest> tempInterests = listService.GetInterestFeeds("");
        foreach (var interest in tempInterests)
        {
            interest._parent = this;
            Interests.Add(interest);
        }
        var pluginLoader = new PluginLoader();
        pluginLoader.EnsureLoaded();
    }
    private ObservableCollection<Interest> _interests;
    public ObservableCollection<Interest> Interests
    {
        get { return _interests; }
        set { _interests = value; RaisePropertyChanged(() => Interests); }
    }

    public ICommand ItemVisibleCommand
    {
        get
        {
            return new MvxCommand<Interest>(item => item.IsVisible = !item.IsVisible);
        }
    }
}

FirstView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    ...>
    <Mvx.MvxListView
        ...
        local:MvxBind="ItemsSource Interests"
        local:MvxItemTemplate="@layout/item_interests" />
</LinearLayout>

item_interests:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="30dp"
        local:MvxBind="Text InterestName" />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        local:MvxBind="Text InterestDescription; Visibility IsVisible, Converter=Visibility" />
</LinearLayout>

为了将它绑定到MvxListView内的TextView,我一直试图将我的代码修改为类似于How to bind ItemClick in MvxListView in MvxListView的类似于Stuart的anwser,导致以下代码:

item_interest:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="30dp"
        local:MvxBind="Text InterestName; Click ItemVisibleCommand" />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        local:MvxBind="Text InterestDescription; Visibility IsVisible, Converter=Visibility" />
</LinearLayout>

FirstViewModel:

public class FirstViewModel
    : MvxViewModel
{
    public FirstViewModel(IListService listService)
    {
        Interests = new ObservableCollection<Interest>();
        List<Interest> tempInterests = listService.GetInterestFeeds("");
        foreach (var interest in tempInterests)
        {
            interest._parent = this;
            Interests.Add(interest);
        }
        var pluginLoader = new PluginLoader();
        pluginLoader.EnsureLoaded();
    }
    private ObservableCollection<Interest> _interests;
    public ObservableCollection<Interest> Interests
    {
        get { return _interests; }
        set { _interests = value; RaisePropertyChanged(() => Interests); }
    }

    public void MakeItemVisible(bool isVisible)
    {
        isVisible = !isVisible;
    }

兴趣:

public class Interest : INotifyPropertyChanged
{
    public string InterestId { get; set; }
    public string InterestName { get; set; }
    public string InterestDescription { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public FirstViewModel _parent { get; set; }

    private bool _isVisible;
    public bool IsVisible
    {
        get { return _isVisible; }
        set
        {
            _isVisible = value;
            onPropertyChanged(this, "IsVisible");
        }
    }

    private void onPropertyChanged(object sender, string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
        }
    }


    public Interest(string id, string name, string description)
    {
        //Initialisers
    }



    private MvxCommand<bool> _itemVisible;
    public ICommand ItemVisibleCommand
    {
        get
        {
            _itemVisible = _itemVisible ?? new MvxCommand<bool>(IsVisible => _parent.MakeItemVisible(IsVisible));
            return _itemVisible;
        }
    }
}

导致以下异常:

04-04 15:05:40.575 I/MonoDroid(18011): UNHANDLED EXCEPTION: System.NullReferenceException: Object reference not set to an instance of an object
04-04 15:05:40.575 I/MonoDroid(18011): at Cirrious.MvvmCross.ViewModels.MvxCommand`1<bool>.Execute (object) <IL 0x00010, 0x00088>
04-04 15:05:40.575 I/MonoDroid(18011): at Cirrious.MvvmCross.Binding.Droid.Target.MvxViewClickBinding.ViewOnClick (object,System.EventArgs) <IL 0x0001f, 0x000fb>
04-04 15:05:40.575 I/MonoDroid(18011): at Android.Views.View/IOnClickListenerImplementor.OnClick (Android.Views.View) [0x0000d] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.12-series/a1e3982a/source/monodroid/src/Mono.Android/platforms/android-15/src/generated/Android.Views.View.cs:1615
04-04 15:05:40.575 I/MonoDroid(18011): at Android.Views.View/IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.12-series/a1e3982a/source/monodroid/src/Mono.Android/platforms/android-15/src/generated/Android.Views.View.cs:1582
04-04 15:05:40.575 I/MonoDroid(18011): at (wrapper dynamic-method) object.a963c1ac-b573-4022-b41d-f0f002438c84 (intptr,intptr,intptr) <IL 0x00017, 0x00043>
Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object

提前感谢任何花时间阅读所有内容的人:)


更新 - 我试图按照斯图尔特的建议去做,并得到以下解决方案: 首先,为了保留原始的Interest实体,它被包装在一个InterestWrapper中。

public class InterestWrapper : INotifyPropertyChanged
{
    private Interest _interest;
    private InterestAndroidViewModel _parent;  //TO-DO
    public Interest Item { get { return _interest; } }

    public event PropertyChangedEventHandler PropertyChanged;

    private bool _isVisible;
    public bool IsVisible
    {
        get { return _isVisible; }
        set
        {
            _isVisible = value;
            onPropertyChanged(this, "IsVisible");
        }
    }

    private void onPropertyChanged(object sender, string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
        }
    }
    public InterestWrapper(Interest interest, InterestAndroidViewModel parent)
    {
        IsVisible = false;
        _interest = interest;
        _parent = parent;
    }

    public IMvxCommand ItemVisibleCommand
    {
        get
        {
            return new MvxCommand(() => _parent.MakeItemVisible(_interest));
        }
    }
}

FirstViewModel

public class FirstViewModel
    : MvxViewModel
{
    public FirstViewModel(IListService listService)
    {
        Interests = new ObservableCollection<InterestWrapper>();
        List<Interest> tempInterests = listService.GetInterestFeeds("");
        foreach (var interest in tempInterests)
        {
            InterestWrapper wrapper = new InterestWrapper(interest, this);
            Interests.Add(wrapper);
        }
    }
    private ObservableCollection<InterestWrapper> _interests;
    public ObservableCollection<InterestWrapper> Interests
    {
        get { return _interests; }
        set { _interests = value; RaisePropertyChanged(() => Interests); }
    }

    public void MakeItemVisible(Interest interest)
    {
        if (interest.IsVisible)
        {
            interest.IsVisible = !interest.IsVisible;
        }
        else
        {
            foreach (var _interest in _interests)
            {
                _interest.Item.IsVisible = false;
            }
            interest.IsVisible = !interest.IsVisible;
        }
    }
}

item_interest:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    ...
    <RelativeLayout
        ...
        <TextView
            ...
            local:MvxBind="Text Item.InterestName; Click ItemVisibleCommand" />
        <Mvx.MvxImageView
            ...
            local:MvxBind="Visibility Item.IsVisible, Converter=InvertedVisibility; Click ShowEducationsCommand" />
    </RelativeLayout>
</RelativeLayout>

2 个答案:

答案 0 :(得分:1)

local:MvxBind="Text InterestName; Click ItemVisibleCommand"只能真正调用非参数化的MvxCommand - 它无法调用MvxCommand<bool>,因为它不知道bool值是什么。< / p>

如果您愿意,可以使用CommandParameter转换器传入值 - 例如local:MvxBind="Text InterestName; Click CommandParameter(ItemVisibleCommand, IsVisible)"

但总的来说,在这种情况下,我可能会建议将ItemVisibleCommand重写为一个&#34;切换可见&#34;改为命令

答案 1 :(得分:0)

通过这个问题看看它是你的那个,并且有斯图尔特建议的解决方案,所以认为这就是你要找的。

Binding button click in ListView template MvvMCross