【问题标题】:mvxlistview click on itemmvxlistview 点击项目
【发布时间】:2014-05-16 20:22:01
【问题描述】:

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

我目前已将大部分内容与 MvvmCross Visibility 插件一起使用,但单击事件绑定到 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);
        }
    }
}

第一视图:

<?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,我一直在尝试根据 Stuart 的回答将我的代码修改为类似于 How to bind ItemClick in MvxListView in MvxListView 的内容,从而得到以下代码:

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

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


更新 - 我尝试按照 Stuart 的建议进行操作,并得到以下解决方案: 首先,为了保留原始的 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));
        }
    }
}

第一视图模型

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>

【问题讨论】:

    标签: xamarin.android xamarin mvvmcross mvxbind


    【解决方案1】:

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

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

    但总的来说,在这种情况下,我可能会建议将 ItemVisibleCommand 重写为“切换可见”命令

    【讨论】:

      【解决方案2】:

      看看这个问题,它是你的问题,并且有 Stuart 建议的解决方案,所以认为这就是你正在寻找的。​​p>

      Binding button click in ListView template MvvMCross

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-08
        • 1970-01-01
        • 1970-01-01
        • 2019-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多