如何突出显示MvxListView中的选定项目

时间:2013-08-21 18:20:25

标签: android mvvmcross

如何在MvxListView中突出显示一个项目,直到它被取消选中或者选择其他项目为止?

我的程序有一个MvxListView,可以正确显示项目列表。用户可以通过单击选择项目,然后单击保存按钮。所选项目存储在MyChosenItem中,直到保存按钮代码需要它为止。当前,所选项目在返回未选定颜色之前会在瞬间保持高亮显示。

这就是MvxListView的创建方式:

<Mvx.MvxListView
    android:layout_width="match_parent"
    android:layout_height="260dp"
    android:layout_marginTop="40dp"
    android:id="@+id/MyMvxListViewControl"
    local:MvxBind="ItemsSource MyItems; SelectedItem MyChosenItem"
    local:MvxItemTemplate="@layout/my_item_layout" />

这是Layout/my_item_layout.xaml

<?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/Project.Ui.Droid"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <TextView
        android:layout_width="300.0dp"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:textSize="20dp"
        android:textColor="#000000"
        local:MvxBind="Text Field1" />
    <TextView
        android:layout_width="250.0dp"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:textSize="20dp"
        android:textColor="#000000"
        local:MvxBind="Text Field2" />
</LinearLayout>

1 个答案:

答案 0 :(得分:7)

此方法提供了一种自定义哪些项目保持突出显示的简便方法。我决定使用它,因为它让我可以完全控制突出显示的内容以及它在列表中的显示方式。 (此示例显示仅突出显示一个项目,但可以轻松扩展以突出显示更多项目。)

  1. 原始问题中的MvxListView链接到关联视图模型中的MyItemsMyChosenItemMyItemsItem的集合,MyChosenItem只是一个Item。我将isItemSelected添加到ItemItem类现在看起来像这样:

    public class Item : MvxViewModel           
    {
        private string _field1;
        private string _field2;
        private bool _isItemSelected = false;
    
        public string Field1
        {
            get { return _field1; }
            set
            {
                _field1= value;
                RaisePropertyChanged("Field1");
            }
        }
    
        public string Field2
        {
            get { return _field2; }
            set
            {
                _field2= value;
                RaisePropertyChanged("Field2");
            }
        }
    
        public bool isItemSelected
        {
            get { return _isItemSelected; }
            set
            {
                _isItemSelected = value;
                RaisePropertyChanged("isItemSelected");
            }
        }
    }
    

    注意:Item类扩展MvxViewModel,以便可以调用RaisePropertyChange()。这允许my_item_layout.xaml在该属性更改时得到通知。

  2. 从MvxListView的isItemSelected绑定的属性更新SelectedItem的每个实例。在这种情况下,这是关联视图模型中的MyChosenItem属性。这就是新代码的样子:

    public Item MyChosenItem
    {
        get { return _myChosenItem; }
        set
        {
            if (_myChosenItem != value)
            {
                _myChosenItem = value;
                UpdateItemSelections();
                RaisePropertyChanged("MyChosenItem");
            }
        }
    }
    
    // Select MyChosenItem and unselect all other items
    private void UpdateItemSelections()
    {
        if( MyItems.Count > 0)
        {
            for (int index = 0; index < MyItems.Count; index++)
            {
                // If the chosen item is the same, mark it as selected
                if (MyItems[index].Field1.Equals(MyChosenItem.Field1)
                    && MyItems[index].Field2.Equals(MyChosenItem.Field2))
                {
                    MyItems[index].isItemSelected = true;
                }
                else
                {
                    // Only trigger the property changed event if it needs to change
                    if (MyItems[index].isItemSelected)
                    {
                        MyItems[index].isItemSelected = false;
                    }
                }
            }
        }
    }
    

    UpdateItemSelections()修改为您想要的任何选择行为非常容易。

  3. 根据isItemSelected属性使每一行执行某些操作。我只是通过控制视图的visibility属性来改变背景颜色。但是,各种各样的事情都是可能的。 isItemSelected甚至可以传递给自定义控件以获得一些非常有趣的视觉效果。我的新Layout/my_item_layout.xaml看起来像这样:

    <?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/Project.Ui.Droid"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    
        <!-- SELECTED BACKGROUND COLOR -->
        <View
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#FF0000"
            local:MvxBind="Visibility isItemSelected,Converter=BoolToViewStates" />
    
        <TextView
            android:layout_width="300.0dp"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:textSize="20dp"
            android:textColor="#000000"
            local:MvxBind="Text Field1" />
        <TextView
            android:layout_width="250.0dp"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:textSize="20dp"
            android:textColor="#000000"
            local:MvxBind="Text Field2" />
    </LinearLayout>
    

  4. 修改

    最好使用MvxCommand,而不是在设置SelectedItem时触发突出显示的操作。似乎SelectedItem仅在尚未选中时才设置。点击一个项目将选择它。点击另一个项目将更改选择。再次点击同一项目将取消选中。这意味着一旦选择了某个项目,就必须保持选中一个项目。如果您需要能够取消选择列表中的所有项目,请按照原始说明进行以下修改:

    1. 向视图模型添加MvxCommand。从UpdateItemSelections()而不是MvxCommand致电MyChosenItem

      public MvxCommand ItemSelectedCommand { get; private set; }
      
      // Constructor
      public ItemSelectionViewModel()
      {
          ItemSelectedCommand = new MvxCommand(OnItemSelected);
      }
      
      public Item MyChosenItem
      {
          get { return _myChosenItem; }
          set
          {
              if (_myChosenItem != value)
              {
                  _myChosenItem = value;
                  //UpdateItemSelections();    // Move this to OnItemSelected()
                  RaisePropertyChanged("MyChosenItem");
              }
          }
      }
      
      private void OnItemSelected()
      {
          UpdateItemSelections();
      }
      
    2. 更改UpdateItemSelections()以切换isItemSelected属性,而不是始终将其设置为true:

      // Select MyChosenItem and unselect all other items
      private void UpdateItemSelections()
      {
          if( MyItems.Count > 0)
          {
              for (int index = 0; index < MyItems.Count; index++)
              {
                  // If the chosen item is the same, mark it as selected
                  if (MyItems[index].Field1.Equals(MyChosenItem.Field1)
                      && MyItems[index].Field2.Equals(MyChosenItem.Field2))
                  {
                      // Toggle selected status
                      MyItems[index].isItemSelected = !MyItems[index].isItemSelected;
                  }
                  else
                  {
                      // Only trigger the property changed event if it needs to change
                      if (MyItems[index].isItemSelected)
                      {
                          MyItems[index].isItemSelected = false;
                      }
                  }
              }
          }
      }
      
    3. 请务必在保存或执行对列表中所选项目执行操作的任何内容时检查MyChosenItem.isItemSelected == trueMyChosenItem中可能存在未在用户看到的列表视图中选择的值。

    4. MvxCommand的布局定义中将ItemClick绑定到MvxListView

      <Mvx.MvxListView
          android:layout_width="match_parent"
          android:layout_height="260dp"
          android:layout_marginTop="40dp"
          android:id="@+id/MyMvxListViewControl"
          local:MvxBind="ItemsSource MyItems; SelectedItem MyChosenItem; ItemClick ItemSelectedCommand"
          local:MvxItemTemplate="@layout/my_item_layout" />