如何在运行时使用DynamicResourceExtension和IValueConverter设置颜色?

时间:2015-03-23 16:42:38

标签: c# wpf xaml

我有一个枚举:

public enum SignalColor
{
    None,
    Signal01A,
    Signal02A
 }

和LightTheme.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                >
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="../Colors.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!--Signal colors-->
<SolidColorBrush x:Key="Signal01ABrush" Color="#8bc34a"/>
<SolidColorBrush x:Key="Signal01BBrush" Color="#5b9914"/>
</ResourceDictionary>

我有SignalColorSelector控件用于选择颜色

<c:SignalColorSelector Name="Test" Grid.Column="0" AllowsTransparent="True" SelectedColor="Signal02A"></c:SignalColorSelector>
<c:SignalColorSelector Name="ChooseColor" Grid.Column="1" Header="Choose a color" SelectedColor="Signal01A"></c:SignalColorSelector>

如何创建一个从MarkupExtension派生并实现IValueConverter的SignalColorToBrushConverter类? 在Convert方法中,值应为SignalColor类型。 如果是SignalColor.None,则返回DependencyProperty.UnsetValue。 否则,使用DynamicResourceExtension 返回相应的信号颜色画笔。

修改1 我创建了类SignalColorToBrushConverter:

 public class SignalColorToBrushConverter : MarkupExtension, IValueConverter
{
    private static DynamicResourceExtension dynamicResource = new DynamicResourceExtension();

    public SignalColorToBrushConverter()
    {
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    public object Convert(object value, Type tagertType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return null;

        SignalColor signalColor = (SignalColor)Enum.Parse(typeof(SignalColor), value.ToString());

        switch (signalColor)
        {
            case SignalColor.None:
                return DependencyProperty.UnsetValue;
            case SignalColor.Signal01A:
                dynamicResource.ResourceKey = "Signal01ABrush";
                break;
            case SignalColor.Signal01B:
                dynamicResource.ResourceKey = "Signal01BBrush";
                break;
            case SignalColor.Signal02A:
                dynamicResource.ResourceKey = "Signal02ABrush";
                break;
            case SignalColor.Signal02B:
                dynamicResource.ResourceKey = "Signal02BBrush";
                break;
        }

        try
        {
            return Application.Current.FindResource(dynamicResource.ResourceKey);
        }
        catch (ResourceReferenceKeyNotFoundException)
        {
            return DependencyProperty.UnsetValue;
        }
    }

然后,使用它:

 <TextBlock Text="Choose a color" Width="100" FontWeight="Bold" HorizontalAlignment="Left"
                                   Foreground="{Binding Path=SelectedColor, Converter={v:SignalColorToBrushConverter}, ElementName=ChooseColor}"/>

1 个答案:

答案 0 :(得分:0)

您可以创建如下所示的标记扩展程序

public class SignalColorExtension : MarkupExtension
{
    public SignalColor IncomingSignalColor
    {
        get;
        set;
    }

    public SignalColorExtension() { }

    public SignalColorExtension(string color)
    {
        SignalColor outColor;
        if (! SignalColor.TryParse(color,true,out outColor))
            IncomingSignalColor = SignalColor.None;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
        var host = target.TargetObject as FrameworkElement;

        if (host != null && IncomingSignalColor != SignalColor.None)
        {
            var colorResourse = host.TryFindResource(IncomingSignalColor.ToString());
            return colorResourse;
        }
        return DependencyProperty.UnsetValue;
    }
}

并在TargetObject上使用find Resource来查找颜色,如果它们存在就像dynamicresource标记一样。然后你可以使用下面的标记:

<Grid Background="{sigColor:SignalColor Signal01A}" >

其中sigColor是我的标记扩展名所在的程序集的命名空间。