Мой вопрос о том, как управлять фоном и цветом текста нескольких кнопок, когда вы читаете нажатие кнопки в MVVM. Чтобы прояснить мой вопрос, пожалуйста, взгляните на интерфейс, который я прикрепил.

UI1

Я уже реализовал это в коде, то есть при нажатии кнопки, я обрабатываю все кнопки отдельно. Исходный фон и цвет текста соответственно белый и черный, и при нажатии любой другой кнопки, кроме 1W, эта кнопка будет выделена. На следующем изображении нажата кнопка 3M

UI2

            lbl3M.BackgroundColor = Color.FromHex(defaultColor);
            lbl3M.TextColor = Color.White;
            if (lbl1M.BackgroundColor != Color.White)
            {
                lbl1M.BackgroundColor = Color.White;
                lbl1M.TextColor = Color.Black;
            }
            if (lbl1W.BackgroundColor != Color.White)
            {
                lbl1W.BackgroundColor = Color.White;
                lbl1W.TextColor = Color.Black;
            }
            if (lbl6M.BackgroundColor != Color.White)
            {
                lbl6M.BackgroundColor = Color.White;
                lbl6M.TextColor = Color.Black;
            }
            if (lbl1Y.BackgroundColor != Color.White)
            {
                lbl1Y.BackgroundColor = Color.White;
                lbl1Y.TextColor = Color.Black;
            }

Я сделал это на каждой нажатой кнопке.

Я знаю, что этот подход не рентабелен, и я хочу узнать, как реализовать в MVVM способ

РЕДАКТИРОВАТЬ: я создал функцию, которая сбрасывает все кнопки на оригинальный пользовательский интерфейс и изменить пользовательский интерфейс при нажатии кнопки

 void ResetButtonUI()
    {
        lbl1W.BackgroundColor = Color.White;
        lbl1W.TextColor = Color.Black;
        lbl1M.BackgroundColor = Color.White;
        lbl1M.TextColor = Color.Black;
        lbl3M.BackgroundColor = Color.White;
        lbl3M.TextColor = Color.Black;
        lbl6M.BackgroundColor = Color.White;
        lbl6M.TextColor = Color.Black;
        lbl1Y.BackgroundColor = Color.White;
        lbl1Y.TextColor = Color.Black;
    }

И на каждой кнопке у меня есть эта логика

         ResetButtonUI();
         button.BackgroundColor = Color.FromHex(defaultColor);
         button.TextColor = Color.White;
0
A for android 14 Фев 2020 в 19:59

2 ответа

Лучший ответ

По сравнению с listview, CollectionView больше подходит для ваших нужд. Listview сложнее разместить горизонтально.

Здесь работает GIF. введите описание изображения здесь

Вот код.

     <CollectionView ItemsSource="{Binding Persons}" HeightRequest="50" SelectionMode="Single" SelectionChanged="CollectionView_SelectionChanged_1" >
            <CollectionView.ItemsLayout>
                <LinearItemsLayout   Orientation="Horizontal" />
            </CollectionView.ItemsLayout>
            <CollectionView.ItemTemplate>
                <DataTemplate>


                    <StackLayout HorizontalOptions="Center"  VerticalOptions="Center" >
                        <Label Text="{Binding FirstName}" FontSize="20"  Margin="20,10,20,0"/>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

Фоновый код.

   BindingContext = new HomepageViewModel();

Общедоступный список лиц {get; устанавливать; }

    public HomepageViewModel() {

        Persons = new List<Person>();
        Persons.Add(new Person() { FirstName = "1W" });
        Persons.Add(new Person() { FirstName = "1M" });
        Persons.Add(new Person() { FirstName = "3M" });
        Persons.Add(new Person() { FirstName = "6M" });
        Persons.Add(new Person() { FirstName = "1Y" });
    }

} Если вы хотите изменить цвет selectItem, вот ссылка об этом. https: //docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/selection#change-selected-item-color

1
Leon Lu - MSFT 17 Фев 2020 в 08:08

Таким образом, есть 5 вариантов, и пользователь должен выбрать один из них.

ViewModel должен содержать 2 свойства:

  • Коллекция всех вариантов
  • Выбранный вариант

Это должно выглядеть так

// ReactiveObject is from ReactiveUI => https://reactiveui.net/
public class MainViewModel : ReactiveObject
{
    private readonly ObservableCollection<TimeSpanItem> _options;
    private TimeSpanItem _selectedOption;

    public ReadOnlyObservableCollection<TimeSpanItem> Options { get; }

    public TimeSpanItem SelectedOption { get => _selectedOption; set => this.RaiseAndSetIfChanged( ref _selectedOption, value ); }

    public MainViewModel()
    {
        _options = new ObservableCollection<TimeSpanItem>();
        Options = new ReadOnlyObservableCollection<TimeSpanItem>( _options );

        _options.Add( new TimeSpanItem( 1, TimeSpanKind.Week ) );
        _options.Add( new TimeSpanItem( 1, TimeSpanKind.Month ) );
        _options.Add( new TimeSpanItem( 3, TimeSpanKind.Month ) );
        _options.Add( new TimeSpanItem( 6, TimeSpanKind.Month ) );
        _options.Add( new TimeSpanItem( 1, TimeSpanKind.Year ) );

        SelectedOption = _options.Last();
    }
}

И некоторые типы данных:

public enum TimeSpanKind
{
    M = 2,
    W = 1,
    Y = 3,

    Week = W,
    Month = M,
    Year = Y,
}

public class TimeSpanItem
{
    public TimeSpanItem( int value, TimeSpanKind kind )
    {
        Value = value;
        Kind = kind;
    }

    public int Value { get; }
    public TimeSpanKind Kind { get; }

    public override string ToString()
    {
        return $"{Value}{Kind}";
    }
}

Теперь пришло время для презентации. Самый простой способ представить коллекцию с возможностью выбора - это ListBox или ListView, потому что все может быть подключено в XAML

<Window
      x:Class="WpfApp1.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="clr-namespace:WpfApp1"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      Title="MainWindow"
      Width="800"
      Height="450"
      mc:Ignorable="d">
<Window.DataContext>
  <local:MainViewModel/>
</Window.DataContext>
    <Grid>

        <ListBox
              HorizontalAlignment="Center"
              VerticalAlignment="Center"
              ItemsSource="{Binding Items}"
              SelectedItem="{Binding SelectedItem}">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel
                          Margin="5"
                          Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock
                          MinWidth="40"
                          Margin="5"
                          Text="{Binding}"
                          TextAlignment="Center" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

    </Grid>
</Window>

И это результат введите описание изображения здесь

0
Sir Rufo 15 Фев 2020 в 19:33