I want to change the color of a WPF control depending on the state of a bool, in this case the state of a checkbox. This works fine as long as I'm working with StaticResources:
My control
<TextBox Name="WarnStatusBox" TextWrapping="Wrap" Style="{DynamicResource StatusTextBox}" Width="72" Height="50" Background="{Binding ElementName=WarnStatusSource, Path=IsChecked, Converter={StaticResource BoolToWarningConverter}, ConverterParameter={RelativeSource self}}">Status</TextBox>
My converter:
[ValueConversion(typeof(bool), typeof(Brush))]
public class BoolToWarningConverter : IValueConverter
{
public FrameworkElement FrameElem = new FrameworkElement();
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
bool state = (bool)value;
try
{
if (state == true)
return (FrameElem.TryFindResource("WarningColor") as Brush);
else
return (Brushes.Transparent);
}
catch (ResourceReferenceKeyNotFoundException)
{
return new SolidColorBrush(Colors.LightGray);
}
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
return null;
}
}
The problem is that I have several definitions of the Resource "WarningColor" dependant on setting day mode or night mode. These events does not trig the WarningColor to change. Is there a way to make the return value dynamic or do I need to rethink my design?
The way to return a dynamic resource reference is pretty simple using a DynamicResourceExtension constructor and supplying it a resource key.
Usage:
return new DynamicResourceExtension(Provider.ForegroundBrush);
Definition of the Provider class should contains the key:
public static ResourceKey ForegroundBrush
{
get
{
return new ComponentResourceKey(typeof(Provider), "ForegroundBrush");
}
}
And the value for the key would be declared in the resource dictionary:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:theme="clr-namespace:Settings.Appearance;assembly=AppearanceSettingsProvider">
<Color x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type theme:Provider}, ResourceId=ForegroundColor}">#FF0000FF</Color>
<SolidColorBrush x:Key="{ComponentResourceKey {x:Type theme:Provider}, ForegroundBrush}" Color="{DynamicResource {ComponentResourceKey {x:Type theme:Provider}, ForegroundColor}}" />
</ResourceDictionary>
This way, the converter would dynamically assign a DynamicResource to the bound property depending on the resource key supplied.
You cannot return something dynamic from a converter, but if your only condition is a bool you can easily replace the whole converter with a Style
using Triggers
:
e.g.
<Style TargetType="TextBox">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=WarnStatusSource}" Value="True">
<Setter Property="Background" Value="{DynamicResource WarningColor}" />
</DataTrigger>
</Style.Triggers>
</Style>
If now the resource with that key is changed the background should change as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With