Reputation: 168
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.
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
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
Reputation: 9224
Compared with listview
, CollectionView
is more suitable for your needs. Listview
is more complicated to place horizontally.
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
Reputation: 19106
So there are 5 options and the user have to choose one of them.
The ViewModel must contain 2 properties:
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>
Upvotes: 0