I've spent all day trying to figure out how I can simply have a list of colors (for example: Colors.AliceBlue) as my ItemsSource for a GridView and bind those colors to a Fill property of a Rectangle inside the DataTemplate. I know the Fill property must be a brush, so I have tried using a converter to convert the color to a SolidColorBrush, but it has not worked. I've also tried not using a converter and instead changing the List to List but that did not work either. No matter what I do, I keep getting binding errors that say:
Converter failed to convert value of type '#FFF0F8FF' to type 'Brush'. Binding: Path='' DataItem='#FFF0F8FF'; target element is 'Microsoft.UI.Xaml.Shapes.Rectangle' (Name='null'); target property is 'Fill' (type 'Brush')
Everything I try always seems to return my color as an ARGB, in this case "#FFF0F8FF", which is not what the property accepts. Any ideas on how to bind my list of colors to my item/data template? I definitely want to use color names in my list, as it is easier to access colors this way rather than looking up their RGB codes and whatnot.
Page.xaml
<GridView ItemsSource="{x:Bind ColorOptions}" IsItemClickEnabled="True" SelectionMode="Single">
<GridView.ItemTemplate>
<DataTemplate>
<Rectangle Fill="{Binding}" Width="40" Height="40" />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Page.xaml.cs
using System.Windows.Media;
...
public readonly List<Color> ColorOptions = new()
{
Colors.AliceBlue,
Colors.Black,
Colors.DarkBlue,
Colors.Brown,
Colors.DarkGreen,
Colors.Magenta
};
Also, if you're interested, here's the converter I created and tried, but also did not work.
BrushConverter.cs
using System.Windows.Media;
using Microsoft.UI.Xaml.Data;
namespace App.Helpers;
public class BrushConverter : IValueConverter
{
public object? Convert(object value, Type targetType, object parameter, string language)
{
return new SolidColorBrush((Color)value);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return ((SolidColorBrush)value).Color;
}
}
Page.xaml (using converter)
<GridView ItemsSource="{x:Bind ColorOptions}" IsItemClickEnabled="True" SelectionMode="Single">
<GridView.ItemTemplate>
<DataTemplate>
<Rectangle Fill="{Binding Converter={StaticResource BrushConverter}}" Width="40" Height="40" />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
CodePudding user response:
Had to change some things as I can't use System.Windows.Media:
- On Page/Window.xaml
<Window
...
xmlns:helpers="using:TestApp.Helpers"
xmlns:vm="using:TestApp.ViewModels"
...>
<Grid>
<Grid.Resources>
<vm:MainViewModel x:Name="ViewModel" />
<helpers:BrushConverter x:Name="BrushConverter" />
</Grid.Resources>
<GridView ItemsSource="{x:Bind ViewModel.ColorOptions, Mode=OneWay}">
<GridView.ItemTemplate>
<DataTemplate>
<Rectangle Width="40" Height="40" Fill="{Binding Converter={StaticResource BrushConverter}}" />
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</Window>
- Use a ViewModel (e.g. MainViewModel.cs)
using System.Collections.Generic;
using System.Drawing;
namespace TestApp.ViewModels;
public class MainViewModel
{
public List<Color> ColorOptions { get; } = new()
{
Color.Red,
Color.Orange,
Color.Yellow
};
}
- BrushConverter.cs (Drawing.Color to Windows.UI.Color) for my end
public object Convert(object value, Type targetType, object parameter, string language)
{
var drawingColor = (System.Drawing.Color)value;
return new SolidColorBrush(Windows.UI.Color.FromArgb(drawingColor.A, drawingColor.R, drawingColor.G, drawingColor.B));
}
CodePudding user response:
This way you don't need a converter:
using Microsoft.UI;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System.Collections.Generic;
using Windows.UI;
namespace GridViews;
public class ColorOption
{
public ColorOption(string name, Color color)
{
Name = name;
Color = new SolidColorBrush(color);
}
public string Name { get; set; }
public Brush Color { get; set; }
}
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
public List<ColorOption> ColorOptions { get; } = new()
{
new ColorOption("Alice Blue", Colors.AliceBlue),
new ColorOption("Black", Colors.Black),
new ColorOption("Dark Blue", Colors.DarkBlue),
new ColorOption("Brown", Colors.Brown),
new ColorOption("Dark Green", Colors.DarkGreen),
new ColorOption("Magenta", Colors.Magenta),
};
}
<GridView
IsItemClickEnabled="True"
ItemsSource="{x:Bind ColorOptions}"
SelectionMode="Single">
<GridView.ItemTemplate>
<DataTemplate x:DataType="local:ColorOption">
<StackPanel>
<TextBlock Text="{x:Bind Name}" />
<Rectangle
Width="40"
Height="40"
Fill="{x:Bind Color}" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>