Home > Mobile >  How to bind a List of colors to property that requires Brush?
How to bind a List of colors to property that requires Brush?

Time:11-13

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:

  1. 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>
  1. 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
    };
}
  1. 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));
}

Output App

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