Theresa Ferguson
Theresa Ferguson

Reputation: 111

Changing the foreground colour of a button

I have a list of contacts, I want to display the alphabet and grey out the letters that do not have corresponding contacts.

in my Model I have:

public class ContactInitial
{
    public string Initial { get; set; }
}

This is derived from the database.

In my View I have the following

<StackPanel Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left"  Width="17">
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">A</Button >
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">B</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">C</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">D</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">E</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">F</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">G</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">H</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">I</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">J</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">K</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">L</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">M</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">N</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">O</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">P</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">Q</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">R</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">S</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">T</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">U</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">V</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">W</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">X</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">Y</Button>
    <Button Height="17" Background="#FFFBF5A6" BorderBrush="{x:Null}">Z</Button>
</StackPanel>

I am struggling to work out how I bind the foreground colour to be grey if the letter is not in the ContactInitial and black if it is.

Thanks for your help

Upvotes: 2

Views: 68

Answers (1)

Rekshino
Rekshino

Reputation: 7325

I would implement it with a style, which you could put to the resources of your window, or your container control, for the style would be applied to all buttons in window/control.

In this style you can put a trigger, which will triggered, if the condition is true. The condition I would check in a multi value converter, which should be used in the binding of you view model property and Content property of the button.

This one should work:

   <Window.DataContext>
        <local:ViewModel ></local:ViewModel>
    </Window.DataContext>
    <Window.Resources>
        <local:ContainsStringConverter x:Key="strContConv"/>
        <Style TargetType="Button">
            <Setter Property="Foreground" Value="Gray"/>
            <Style.Triggers>
                <DataTrigger Value="true">
                    <DataTrigger.Binding>
                        <MultiBinding Converter="{StaticResource strContConv}">
                            <Binding Path="InitialString"/>
                            <Binding RelativeSource="{RelativeSource Self}" Path="Content"/>
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Foreground" Value="Black"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

using System;
    using System.Globalization;
    using System.Linq;
    using System.Windows.Data;
    public class ContainsStringConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values==null || values.Length<2 || !values.All(v=>v is string))
            {
                return false;
            }
            var retVal = true;
            var initalStr = values[0] as string;
            for (int i = 1; i < values.Length; i++)
            {
                retVal &= initalStr.Contains(values[i] as string);
            }
            return retVal;
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
        _initialString = Model.Initial;
    }
    public ContactInitial Model { get; set; } = new ContactInitial { Initial = "AC" };

    public string InitialString
    {
        get
        {
            return _initialString;
        }
        set
        {
            if (value != _initialString)
            {
                _initialString = value;
                Model.Initial = _initialString;
                NotifyPropertyChanged(nameof(InitialString));
            }
        }
    }
    private string _initialString;
}

Upvotes: 2

Related Questions