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}}"/>
Related
I have a DataGrid containing four rows, and I would need to make the texts in the last row bold, in order to better separate them from the rows above.
I tried the methods available in the question How to change a single datagrid row FontWeights to Bold?, but I was unable to get it working.
This is the code that I tried; running it results in an error, as row is null.
Setter bold = new Setter(TextBlock.FontWeightProperty, FontWeights.Bold, null);
DataGridRow row = (DataGridRow)DG_PPC.ItemContainerGenerator.ContainerFromIndex(3);
Style newStyle = new Style(row.GetType());
newStyle.Setters.Add(bold);
row.Style = newStyle;
I would appreciate any help you can give me. Thank you!
XAML code:
<DataGrid x:Name="DG_PPC" HorizontalAlignment="Left" Height="115" Margin="661,-6,0,0"
HeadersVisibility="Column" VerticalAlignment="Top" Width="726.25"
Loaded="DataGrid_PPC_Loaded" RowHeaderWidth="0" AutoGenerateColumns="False"
CanUserSortColumns="False" CanUserReorderColumns="False" FontSize="12" IsReadOnly="True">
I found myself another way to do it, which is compatible with my code. Here's the solution, in case someone will be needing something similar.
APP.XML:
<Application.Resources>
<local:FontWeightConverter x:Key="FontWeightConverter"/>
</Application.Resources>
XAML:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="FontWeight" Value="{Binding RelativeSource={RelativeSource Self},
Path=Item.XYZ, Converter={StaticResource FontWeightConverter}}"/>
</Style>
</DataGrid.RowStyle>
Code:
class FontWeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string name = (string)value;
if (name.Equals("Δ"))
return FontWeights.Bold;
else
return FontWeights.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Is there a way that I can use a normal Rectangle (shape) as part of a clip for another object in XAML. It seems like I should be able to, but the solution is eluding me..
<Canvas>
<Rectangle Name="ClipRect" RadiusY="10" RadiusX="10" Stroke="Black" StrokeThickness="0" Width="32.4" Height="164"/>
<!-- This is the part that I cant quite figure out.... -->
<Rectangle Width="100" Height="100" Clip={Binding ElementName=ClipRect, Path="??"/>
</Canvas>
I know that I can use a 'RectangleGeometry' type approach, but I am more interested in the solution in terms of the code presented above.
Try Shape.RenderedGeometry Property.
<Rectangle Width="100" Height="100"
Clip="{Binding ElementName=ClipRect, Path=RenderedGeometry}" />
ClipRect.DefiningGeometry nd ClipRect.RenderedGeometry contain only the RadiusX and RadiusY values but not also Rect.
I'm not sure what exactly you want to achieve (it's not clear to me from your sample) but you could write an IValueConverter which would extract the info you require from the referenced Rectangle:
public class RectangleToGeometryConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var rect = value as Rectangle;
if (rect == null || targetType != typeof(Geometry))
{
return null;
}
return new RectangleGeometry(new Rect(new Size(rect.Width, rect.Height)))
{
RadiusX = rect.RadiusX,
RadiusY = rect.RadiusY
};
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
You would then use this converter in your binding definition:
<Rectangle Width="100" Height="100"
Clip="{Binding ElementName=ClipRect, Converter={StaticResource RectangleToGeometryConverter}}">
Of course you need to add the converter to your resources first:
<Window.Resources>
<local:RectangleToGeometryConverter x:Key="RectangleToGeometryConverter" />
</Window.Resources>
I have a WPF App that has (so far) 2 modes of display, regularmode and widgetmode.
I am using Prism 6 with MVVM design pattern.
MainWindowViewModel knows the mode of display.
ToolBarView has, as expected, a toolbar of buttons and the buttons shall be dynamically changed to different images depending on the mode of the view. If the mode is WidgetMode, it switches to the image with an identical name but with an '_w' added. So instead of "image.png", it's "image_w.png".
What I'd like to do is create a string in ToolBarView that is updated to either String.Empty or to "_w", depending on the mode. I'd also like the image root folder to be a global string, rather than a hardcoded string, so I have defined that in app.xaml.
<Application.Resources>
<sys:String x:Key="ImageURIRoot">/MyApp;component/media/images/</sys:String>
</Application.Resources>
Then in my toolbarview (a usercontrol), I did this:
<UserControl.Resources>
<converters:StringToSourceConverter x:Key="strToSrcConvert"/>
<sys:String x:Key="BtnImgSuffix">_w</sys:String>
.
.
.
</UserControl.Resources>
Note that the string is hardcoded; eventually, I will change it dynamically based off the windowmode.
I then put the Buttons in a Listbox
<ListBoxItem Style="{StaticResource MainButton_Container}">
<Button Command="{Binding ButtonActionDelegateCommand}" Style="{StaticResource Main_Button}">
<Image Source="{Binding Source={StaticResource ImageURIRoot}, Converter={StaticResource strToSrcConvert}, ConverterParameter='{}{0}button.png'}" />
</Button>
</ListBoxItem>
Converter code:
public class StringToSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter is string)
{
return string.Format(parameter.ToString(), value);
}
return null;
}
public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
So that works. But what I want is to have the ConverterParameter equal "{}{0}button{1}.png", where {0} is the URI Root and {1} is the suffix. But I can't figure out how to do it. I know it's simple, but I can't put my finger on it!
Please help!
Figured it out and it was through multibinding. The way I did it was create a converter that inherits from IMultiValueConverter. Its "Convert" method looks like this:
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
ImageSourceConverter conv = new ImageSourceConverter();
int suffixPos = ((String)parameter).Length - 4;
var returnValue = ((String)parameter).Insert(suffixPos, values[1].ToString());
returnValue = Path.Combine(values[0].ToString(), returnValue);
ImageSource imgsrc = conv.ConvertFromString(returnValue) as ImageSource;
return imgsrc;
}
The xaml looks like this:
<Image Height="30" Width="40" diag:PresentationTraceSources.TraceLevel="High">
<Image.Source>
<MultiBinding Converter="{StaticResource stringsToSrcConvert}" ConverterParameter="buttonImg.png">
<Binding Source="{StaticResource ImageURIRoot}"/>
<Binding Source="{StaticResource BtnImgSuffix}"/>
</MultiBinding>
</Image.Source>
</Image>
Also, had to modify the URIRoot
<Application.Resources>
<sys:String x:Key="ImageURIRoot">pack://application:,,,/MyApp;component/media/images/</sys:String>
</Application.Resources>
Thanks, Clemens!
I've included the StringTruncator converter in my App.Resources
xmlns:app="clr-namespace:Tabbed_Browser">
<!--Application Resources-->
<Application.Resources>
<ResourceDictionary>
<app:StringTruncator x:Key="StringTruncator" />
<app:StringTruncatorFav x:Key="StringTruncatorFav" />
<app:AppInfo x:Key="AppInfo" />
<app:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /
</ResourceDictionary>
</Application.Resources>
Then in the UserControl XML I refer to it via this code
<Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
<TextBlock TextWrapping="NoWrap" x:Name="txtPageTitle"
Text="{Binding BrowserViewModel.PageTitle, Converter={StaticResource StringTruncator}}"
FontSize="{StaticResource PhoneFontSizeSmall}"
VerticalAlignment="Top"/>
The StringTruncator is a simple converter that append ... if the string exceed certain length.
namespace Tabbed_Browser
{
public class StringTruncator : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return "";
string str = value.ToString();
int maxChars = 44;
return str.Length <= maxChars ? str : str.Substring(0, maxChars) + "...";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
But then I run the project I get the following. Removing the StringTruncator converter in the code eliminate the error but I need to use the converter. What am I missing?
{System.Windows.Markup.XamlParseException:
Cannot find a Resource with the Name/Key StringTruncator [Line: 15 Position: 22]
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at Tabbed_Browser.User_Controls.UCAddressBar.InitializeComponent()
at Tabbed_Browser.User_Controls.UCAddressBar..ctor()}
You should use DynamicResource instead, this way it will be applied at runtime. Or you can add resources to the Usercontrol.Resources itself. Or you can do like that also, but you must add namespace to UserControl also:
Text="{Binding BrowserViewModel.PageTitle, Converter={app:StringTruncator}}"
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.