Binding Hex value to Color in XAML - c#

I have objects stored in a database that I am displaying in a GridView. I am binding each of their properties from the database. The color property is stored as a Hex value.
I am trying to bind this hex value using a converter function as shown below and just returning Red every time for now.
It seems to be working but it eventually returns the following error:
The program '[5548] TranslatorService.Example.exe: Managed (v4.0.30319)' has exited with code -1073741189 (0xc000027b).
Can anyone tell me what I am doing wrong?
The code-behind:
public class StringToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, String language)
{
return Colors.Red;
}
public object ConvertBack(object value, Type targetType, object parameter, String language)
{
throw new NotImplementedException();
}
}
The XAML:
<Grid.Background>
<SolidColorBrush Color="{Binding Path=ColorHex, Converter={StaticResource ColorConverter}}" />
</Grid.Background>
Thank you

In my experience you need to assing a Brush, not a Color:
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(255, 255, 0, 0);
or
mySolidColorBrush.Color = Color.Red;

The problem seems to be resolved after recompiling.

In your posted converter code, you are returning Color.Red, so no matter what value is, you'll get Red every time.

Related

Invert static resource dictionaries colors programmatically wpf

I have the following colors in my colorPalette.xaml file and I was curious to know...
Is its possible for me to loop through colors in my resource dictionary programmaticly and invert the color values?
Similar to taking an image in photoshop and adding the invert filter. I ask because I'd prefer to not make a duplicate xaml file where I manually invert the colors. I'd rather it be a more procedural solution.
<Color x:Key="Accent01">#1d7b87</Color>
<Color x:Key="Accent02">#28aabc</Color>
<Color x:Key="ColorWhite">White</Color>
<Color x:Key="ColorBlack">Black</Color>
<Color x:Key="Color01">#e0e0e0</Color>
<Color x:Key="Color02">#c3c5c7</Color>
<Color x:Key="Color03">#a6a9ad</Color>
<Color x:Key="Color04">#8b8f94</Color>
<Color x:Key="Color05">#71757a</Color>
<Color x:Key="Color06">#585c61</Color>
<Color x:Key="Color07">#404347</Color>
<Color x:Key="Color08">#292b2e</Color>
<Color x:Key="Color09">#1e1f21</Color>
<Color x:Key="Color10">#121314</Color>
after loading the directory you can loop on it's items and change thier values by using the keys Property it should be something like this :
foreach(object keyy in RescourcesDir.Keys)
{
//get the object and it's value
object val = RescourcesDir[keyy];
//change it's value ...
RescourcesDir[keyy] = somevalue;
}
try to take a look at this thread it may help you getting your rescourcesdirectory
Ahmad's solution is great if you don't mind changing the values. But what if you want to keep the original values and have the inverted versions?
Let's say you have a folder named Converters and in it you create the two following IValueConverter classes:
The base class converting a System.Windows.Media.Color to a System.Windows.Media.SolidColorBrush:
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace WPFTest.Converters
{
public class ColorToBrush : IValueConverter
{
public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value is Color ? new SolidColorBrush((Color)value) : Brushes.Black;
}
public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
An inheriting class to invert the color - using any of these methods - then convert it to a brush:
using System;
using System.Globalization;
using System.Windows.Media;
namespace WPFTest.Converters
{
public class InvertColorToBrush : ColorToBrush
{
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Color)
{
Color color = (Color)value;
int iCol = ((color.A << 24) | (color.R << 16) | (color.G << 8) | color.B) ^ 0xffffff;
Color inverted = Color.FromArgb((byte)(iCol >> 24),
(byte)(iCol >> 16),
(byte)(iCol >> 8),
(byte)(iCol));
return base.Convert(inverted, targetType, parameter, culture);
}
else
{
return Brushes.Black;
}
}
public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Note: Gray-scale color's inversions are less dramatic, so for this example I added:
<Color x:Key="Blue">#0000ff</Color>
<Color x:Key="Yellow">#ffff00</Color>
Then in xaml you add your reference:
xmlns:converters="clr-namespace:WPFTest.Converters"
Declare your keys:
<converters:ColorToBrush x:Key="BrushColor" />
<converters:InvertColorToBrush x:Key="BrushInvertColor" />
And usage:
<Label
Content="COLOR TEST"
Background="{Binding Converter={StaticResource BrushColor}, Mode=OneWay, Source={StaticResource Blue}}"
Foreground="{Binding Converter={StaticResource BrushColor}, Mode=OneWay, Source={StaticResource Yellow}}"/>
<Label
Content="COLOR INVERT TEST"
Background="{Binding Converter={StaticResource BrushInvertColor}, Mode=OneWay, Source={StaticResource Blue}}"
Foreground="{Binding Converter={StaticResource BrushInvertColor}, Mode=OneWay, Source={StaticResource Yellow}}"/>

Formatting a bound property

I want to bind Value of a Slider to a Content of a Label. The value of the slider sets a timespan. The value of the slider is a timespan in minutes (value 5 = 5 minutes).
This is my XAML for the Label:
<Label
Content="{Binding Value, ElementName=sld_Timespan}"
ContentStringFormat="{}{0:HH:mm}"
/>
I can bind them. The values are correct. But the format is wrong.
For ContentStringFormat i tried different settings, like on this (TextBlock in Silverlight) or this (TextBlock Multibinding) site. I also took the data binding dialog and set the StringFormat to {0:G} (you can choose this from a ComboBox) or other settings.
I only get a value "formatted" as double, like "1" or "13.423523423".
I also tried TextBlock. The same problem.
What is wrong with my XAML code?
After the comment of Clemens i understood what was wrong. I wrote a simple Converter:
public class DoubleToTimespanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return TimeSpan.FromMinutes((double)value).ToString(#"hh\:mm\:ss");
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And added to my XAML:
<UserControl.Resources>
<!--local is my local namespace-->
<local:DoubleToTimespanConverter x:Key="converter"/>
</UserControl.Resources>
And i could easily set "converter" as my converter.

change Text/DataFormat of Slider's ThumbTooltip

I have a slider with maximum value of video's time in seconds (1 minute = 60 seconds, so if the video is 60 seconds length, the maximum value of the slider will be 60).
When I drag the Thumb, there's ThumbTooltip that shows the current value I am hovering.
I want to change that text so instead of displaying int, it will display time 1 will be 00:01 and so on...
I tried to play with the style of the Slider with no luck.
Will appreciate your help.
Slider has ThumbToolTipValueConverter property. You need to create class which implements IValueConverter interface. In that the Convert method will help you to convert the default slider value to your customized value. See the below code.
XAML
<Page.Resources>
<local:SliderValueConverter x:Key="SliderValueConverter"/>
</Page.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Slider Maximum="60" Value="40" Height="100" Width="300" ThumbToolTipValueConverter="{StaticResource SliderValueConverter}" />
</Grid>
SliderValueConverter.cs
public class SliderValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var seconds = System.Convert.ToInt32(value);
return string.Format("{0:00}:{1:00}", (seconds / 60) % 60, seconds % 60);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}

how is the foreground color changed on just one line of wpf listbox?

how is the foreground text color changed (not the selected text, or the background of the selection) in a wpf listbox? say, for example, i wanted to make all the letter "a" items green, all the letter "b" items red, etc? how can i programmatically do that as i add them in c#? all i can find is people posting about changing selected text, i want to change the color of the foreground text to make it look more organized .
on a side note, why is stackoverflow giving me problems about this question? says the question "doesn't meet quality standards". i think this is a perfectly legitimate question. what filter is put on this question that makes it not meet any standards?
i'm looking to do this:
string[] pics= Directory.GetFiles(#"C:\\", "*.jpg");
foreach (string pic in pics)
{
CHANGE THE FOREGROUND COLOR TO RED
lbxFileList.Items.Add(pic);
}
string[] vids= Directory.GetFiles(#"C:\\", "*.mpg");
foreach (string vid in vids)
{
CHANGE THE FOREGROUND COLOR TO GREEN
lbxFileList.Items.Add(vid);
}
Use a template in combination with a converter:
<ListBox x:Name="lbxFileList">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=.}" ForeGround={Binding ., Converter={StaticResource ItemToBrushConverter}}/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The converter should convert your Item to a Brush that has the color you want:
class FileNameToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
return value.EndsWith("mpg") ? Brushes.Green : Brushes.Red;
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
throw new NotImplementedException();
}
}
I agree with the previous answer, but you could also add listboxitems to your listbox (instead of strings), that way you could change the foreground color before adding it to the listbox.
To build on the above solution:
foreach (string pic in pics)
{
if (string.IsNullOrEmpty(pic))
continue;
string first = pic.Substring(0, 1);
Color color;
switch (first.ToLower())
{
case "a":
color = Colors.Green;
break;
case "b":
color = Colors.Red;
break;
default:
color = Colors.Black;
}
ListBoxItem item = new ListBoxItem() {
Content = pic,
Foreground = new SolidColorBrush(color)
};
lbxFileList.Items.Add(pic);
}

WPF Binding to change fill color of ellipse

How do I programmatically change the color of an ellipse that is defined in XAML based on a variable?
Everything I've read on binding is based on collections and lists -can't I set it simply (and literally) based on the value of a string variable? string color = "red" color = "#FF0000"
It's worth pointing out that the converter the other posts reference already exists, which is why you can do <Ellipse Fill="red"> in xaml in the first place. The converter is System.Windows.Media.BrushConverter:
BrushConverter bc = new BrushConverter();
Brush brush = (Brush) bc.ConvertFrom("Red");
The more efficient way is to use the full syntax:
myEllipse.Fill = new SolidColorBrush(Colors.Red);
EDIT in response to -1 and comments:
The code above works perfectly fine in code, which is what the original question was asking about. You also don't want an IValueConverter - these are typically used for binding scenarios. A TypeConverter is the right solution here (because you're one-way converting a string to a brush). See this article for details.
Further edit (having reread Aviad's comment): you don't need to explicitly use the TypeConverter in Xaml - it's used for you. If I write this in Xaml:
<Ellipse Fill="red">
... then the runtime automagically uses a BrushConverter to turn the string literal into a brush. That Xaml is essentially converted into the equivalent longhand:
<Ellipse>
<Ellipse.Fill>
<SolidColorBrush Color="#FFFF0000" />
</Ellipse.Fill>
</Ellipse>
So you're right - you can't use it in Xaml - but you don't need to.
Even if you had a string value that you wanted to bind in as the fill, you don't need to specify the converter manually. This test from Kaxaml:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<Page.Resources>
<s:String x:Key="col">Red</s:String>
</Page.Resources>
<StackPanel>
<Ellipse Width="20" Height="20" Fill="{Binding Source={StaticResource col}}" />
</StackPanel>
</Page>
Strangely, you can't just use the StaticResource col and still have this work - but with the binding it and automatically uses the ValueConverter to turn the string into a brush.
what you will need to do is implement a custom converter to convert the colour to the brush object. Something like this...
public class ColorToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
System.Drawing.Color col = (System.Drawing.Color)value;
Color c = Color.FromArgb(col.A, col.R, col.G, col.B);
return new System.Windows.Media.SolidColorBrush(c);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
SolidColorBrush c = (SolidColorBrush)value;
System.Drawing.Color col = System.Drawing.Color.FromArgb(c.Color.A, c.Color.R, c.Color.G, c.Color.B);
return col;
}
}
And then specify that converter in your binding
Fill="{Binding Colors.Red, Converter={StaticResource ColorToBrushConverter }"
use
System.Windows.Media
If the name of your ellipse in your XAML is my_ellipse,
write something like this:
my_ellipse.Fill = System.Windows.Media.Brushes.Red;
or this:
my_ellipse.Fill = (SolidColorBrush)new BrushConverter().ConvertFromString("#F4F4F5")
A quick work around for this (Although its not binding, and less efficient) is to check the status of an object/element and update the new/other object(s) based on the status, I'll provide a Basic Example Below.
You can do this in MVVM by getting the status of MainWindow Objects from a User Control and changing whatever you want from the MainWindow object status.
Note: this will not work for 2 themed applications and other scenarios where more than basic use case is needed. (Example: Dark Mode, Etc)
In my example, I am using data to draw a "text" on screen (FrontFog_Text, Which is why the text is using the .Fill Property in my case).
I am not using this in my application but came across this when testing a few things so I thought I would share in this thread while I search for my answer!
private void FrontFog_ToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
if (((MainWindow)App.Current.MainWindow).Theme_Control.IsChecked == true)
{
FrontFog_Text.Fill = new SolidColorBrush(System.Windows.Media.Colors.White);
}
else if (((MainWindow)App.Current.MainWindow).Theme_Control.IsChecked == false)
{
FrontFog_Text.Fill = new SolidColorBrush(System.Windows.Media.Colors.Black);
}
}

Categories

Resources