A for android
A for android

Reputation: 168

Handle multiple button views

My question is about how to control the background and text color of multiple buttons when you read a button click in MVVM. To make my question a bit clear please have a look at the UI I have attached.

UI1

I have already implemented this on code behind i.e on button click, I am handling all of the buttons separately. The original background and text color are white and black respectively and when you click on any other button except 1W that button will be highlighted. In the next image, 3M is clicked

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;
            }

I have done this on each button clicked.

I know this approach is not cost-effective and I want to learn how to implement in MVVM way

EDIT: I have created a function which reset all the buttons to Original UI and change the UI on button clicked

 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;
    }

and on each button i have this logic

         ResetButtonUI();
         button.BackgroundColor = Color.FromHex(defaultColor);
         button.TextColor = Color.White;

Upvotes: 0

Views: 619

Answers (2)

Leon Lu
Leon Lu

Reputation: 9224

Compared with listview, CollectionView is more suitable for your needs. Listview is more complicated to place horizontally.

Here is running GIF. enter image description here

Here is code.

     <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>

Background code.

   BindingContext = new HomepageViewModel();

public List Persons { get; set; }

    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" });
    }

} If you want to change the selectItem color, here is a link about it. https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/selection#change-selected-item-color

Upvotes: 1

Sir Rufo
Sir Rufo

Reputation: 19106

So there are 5 options and the user have to choose one of them.

The ViewModel must contain 2 properties:

  • Collection of all options
  • Selected option

It should look like this

// 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();
    }
}

and some data types:

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}";
    }
}

Now it is time for the presentation. The easiest way to present a selectable collection is a ListBox or ListView because everything can be wired up in 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>

and that is the result enter image description here

Upvotes: 0

Related Questions