Как выделить выбранный элемент в MvxListView

Как сохранить элемент в 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>

person Josh    schedule 21.08.2013    source источник
comment
Помогает ли stackoverflow.com/questions/5058291/?   -  person Stuart    schedule 21.08.2013


Ответы (1)


Этот метод обеспечивает простой способ настроить, какие элементы остаются выделенными. Я остановился на этом, потому что это дает мне полный контроль над тем, что выделено и как это отображается в списке. (В этом примере показано выделение только одного элемента, но его можно легко расширить, чтобы выделить больше.)

  1. MvxListView в исходном вопросе ссылается на MyItems и MyChosenItem в связанной модели представления. MyItems — это набор Item, а MyChosenItem — это всего лишь один Item. Я добавил isItemSelected к Item. Класс Item теперь выглядит так:

    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. Обновите каждый экземпляр isItemSelected из свойства, к которому привязывается SelectedItem MvxListView. В данном случае это свойство 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. Я только что изменил цвет фона, управляя свойством видимости представления. Однако возможно всякое. 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>
    

ИЗМЕНИТЬ

Возможно, было бы лучше использовать 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 == true при сохранении или выполнении каких-либо действий с выбранным элементом в списке. В MyChosenItem может быть значение, которое не выбрано в представлении списка, которое видит пользователь.

  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" />
    
person Josh    schedule 23.08.2013
comment
Осторожно: порядок привязок имеет значение! Сначала у меня была привязка ItemClick до привязки SelectedItem, которая не работала. Когда я переключил два (SelectedItem, а затем ItemClick), все начало работать. - person Dribbel; 18.02.2014