I have a CollectionView<T> with 2 columns.
The SelectionMode=Single.
Problem :
The second column displays only a few colors names,
not all and after a selection no more color names !
I use Visual Studio 2022 17.11.5 Maui Android C#.
I haven't found a solution to this problem for a few days now.
Files xaml and code and display are below.
The binding for ColorValue and ColorName are the same although
the colors display well but not the names of these colors !
Do someone can explain me what fault I do, please ? Thank you
.
File PickColorPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:helpers="clr-namespace:Helpers"
xmlns:vm="clr-namespace:ViewsViewModels"
BackgroundColor="White"
x:Class="ViewsViewModels.PickColorPage"
x:Name="PickColorPageName"
Title="Help">
<Shell.BackButtonBehavior>
<BackButtonBehavior IsVisible="False"/>
</Shell.BackButtonBehavior>
<Shell.TitleView>
<Grid ColumnDefinitions="*">
<Label Text="{Binding Title, Source={x:Reference PickColorPageName}}" HorizontalOptions="Center" VerticalOptions="Center" FontSize="32" FontAttributes="Bold"/>
</Grid>
</Shell.TitleView>
<ContentPage.Resources>
<ResourceDictionary>
<helpers:ColorToRGBConverter x:Key="ColorToRGBConverter"/>
</ResourceDictionary>
</ContentPage.Resources>
<Grid RowDefinitions="auto,*,auto">
<Label Text="{Binding Setting.SettingDescription, Source={x:Reference PickColorPageName}}"
BackgroundColor="LightCyan" TextDecorations="Underline" FontSize="16" FontAttributes="Bold" HorizontalOptions="CenterAndExpand"/>
<CollectionView x:Name="cv" Grid.Row="1" ItemsSource="{Binding ListOfColors, Source={x:Reference PickColorPageName}}" Loaded="cv_Loaded"
ItemSizingStrategy="MeasureFirstItem" SelectionMode="Single" SelectionChanged="cv_SelectionChanged">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="auto,*">
<Border Grid.Column="0" StrokeShape="RoundRectangle 10,0,0,10" StrokeThickness="1" Stroke="Red" WidthRequest="180" BackgroundColor="Beige">
<BoxView Color="{Binding ColorValue, Converter={StaticResource ColorToRGBConverter}}"
CornerRadius = "10" HeightRequest = "32" WidthRequest="120" HorizontalOptions="CenterAndExpand" Margin="10"/>
</Border>
<Label Grid.Column="1" Text="{Binding ColorName}" VerticalOptions="Center" FontSize="20" FontAttributes="Bold" Margin="10" HorizontalTextAlignment="Start"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Grid Grid.Row="2" ColumnDefinitions="*,*" BackgroundColor="LightYellow" VerticalOptions="End" HorizontalOptions="FillAndExpand" x:DataType="vm:MainViewModel">
<Button Grid.Column="0" Text="Save" Margin="20,4" Padding="20,0" FontSize="20" Command="{Binding SaveSettingsCommand}"/>
<Button Grid.Column="1" Text="Cancel" Margin="20,4" Padding="20,0" FontSize="20" Clicked="Cancel"/>
</Grid>
</Grid>
</ContentPage>
File PickColorPage.xaml.cs
using System.Collections.ObjectModel;
using Models;
namespace ViewsViewModels
{
public partial class PickColorPage : ContentPage, IQueryAttributable, INotifyPropertyChanged
{
public Setting Setting { get; set; }
public Setting StartSetting { get; set; }
void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query)
{
if (query.Values.Count == 0) return;
Setting = query.Values.ElementAt(0) as Setting;
StartSetting = new Setting(Setting);
OnPropertyChanged(nameof(Setting));
InitColorsList();
System.Diagnostics.Debug.WriteLine($"**************** ListofColors => {ListOfColors.Count}");
// int i = 0; foreach (ClColor c in ListOfColors) { i++; System.Diagnostics.Debug.WriteLine($"{i} => {c.ColorName}"); }
}
public ObservableCollection<ClColor> ListOfColors { get; } = [];
public PickColorPage(MainViewModel vm)
{
InitializeComponent();
BindingContext = vm;
}
public partial class ClColor : ObservableObject
{
[ObservableProperty]
public string colorName;
[ObservableProperty]
public string colorValue;
public ClColor(string _colorName, string _colorValue)
{
ColorName= _colorName;
ColorValue= _colorValue;
}
}
public void InitColorsList()
{
System.Drawing.Color c;
List<string> ls = GetListOfColors();
ListOfColors.Clear();
foreach (string s in ls)
{
c = System.Drawing.Color.FromName(s);
string chex = ToHexString(c);
string settingColor = (string)Setting.SettingValue;
bool rdbtn = chex.Equals(settingColor, StringComparison.InvariantCultureIgnoreCase);
ListOfColors.Add(new ClColor(s, chex));
}
// int i = 0; foreach(ClColor r in ListOfColors) { Console.WriteLine($"{i} => {r.RdbtnChecked}"); i++; }
}
private static string ToHexString(System.Drawing.Color color)
{
byte r = color.R;
byte g = color.G;
byte b = color.B;
// byte a = color.A;
// return string.Format("#{0,2:X2}{1,2:X2}{2,2:X2}{3,2:X2}", r, g, b, a);
return string.Format("#{0,2:X2}{1,2:X2}{2,2:X2}", r, g, b);
}
public static List<string> GetListOfColors()
{
List<string> colorList = [];
// Get type of KnownColor enum
var color = typeof(System.Drawing.KnownColor);
// Enumerate all known color names in enum
var colors = Enum.GetValues(color);
// Remove 27 elements from beginning & 7 elements from the end (windows controls)
var from = 26;
var to = colors.Length - 8;
// Only keep color names and not user interface colors
for (int i = from; i < to; i++) colorList.Add(colors.GetValue(i).ToString());
// Return filtered color list
return colorList;
}
private async void cv_Loaded(object sender, EventArgs e)
{
await Task.Delay(1000); // it seems a bug exists in ScrollTo(), hence this delay to PARTIALLY solve this problem
ClColor clc = ListOfColors.FirstOrDefault(predicate: cl => cl.ColorValue == (string)Setting.SettingValue);
cv.ScrollTo(clc, group:null, position: ScrollToPosition.Center, animate: false); // false because scroll does work very badly !!!
cv.SelectedItem = clc;
}
ClColor? previousSelection = null;
private void cv_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
previousSelection = e.PreviousSelection.FirstOrDefault() as ClColor;
ClColor? x = e.CurrentSelection.FirstOrDefault() as ClColor;
Setting.SettingValue = x.ColorValue;
}
public void Cancel(object sender, EventArgs e)
{
Setting.SettingValue = StartSetting.SettingValue;
OnPropertyChanged(nameof(Setting));
Shell.Current.GoToAsync("..");
}
}
}
File ConfigModels.cs
using CommunityToolkit.Mvvm.ComponentModel;
namespace Models
{
public class Setting : ObservableObject
{
public Setting() { SettingDescription = ""; SettingType = null; SettingValue = Colors.White; }
public Setting(Setting s) { SettingDescription = s.SettingDescription; SettingType = s.SettingType; SettingValue = s.SettingValue; }
public Setting(string desc, Type type, object val) { SettingDescription = desc; SettingType = type; SettingValue = val; }
private string settingDescription;
public string SettingDescription
{
get { return settingDescription; }
set { SetProperty(ref settingDescription, value); }
}
private Type? settingType; // color or double
public Type SettingType
{
get => settingType;
set { SetProperty(ref settingType, value); }
}
private object settingValue;
public object SettingValue
{
get { return settingValue; }
set { SetProperty(ref settingValue, value); }
}
}
MainViewModeland theColorConverter. In addition, did you know theColorTypeConvertercan convert the colorname to color directly?