使用IValueConverter进行动态样式绑定

时间:2012-08-21 18:20:05

标签: wpf custom-controls

我正在尝试在加载用户控件时动态设置一个在App.xaml中定义的样式,并且由于某种原因它没有应用样式(即没有发生错误,它只是没有应用风格)。

我确定这是因为我已经定义了绑定错误,但是我无法弄清楚我需要采取哪些不同的方法才能让它发挥作用。

App.xaml样式

我所追求的风格是RunningTitleBlock,它包含了我在下面的代码示例中包含的其他几种风格。

<Style TargetType="Label">
    <Setter Property="Margin" Value="4"/>
</Style>

<Style TargetType="Label"
       BasedOn="{StaticResource {x:Type Label}}"
       x:Key="HeaderBlock">
    <Setter Property="FontSize" Value="16"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="Foreground" Value="White"/>
</Style>

<Style TargetType="Label"
       BasedOn="{StaticResource ResourceKey=HeaderBlock}"
       x:Key="TitleBlock">
    <Setter Property="Foreground" Value="Black"/>
</Style>

<Style TargetType="Label"
       BasedOn="{StaticResource ResourceKey=TitleBlock}"
       x:Key="RunningTitleBlock">
    <Setter Property="Background">
        <Setter.Value>
            <LinearGradientBrush StartPoint="0.0, 0.5"
                                 EndPoint="1.0, 0.5">
                <GradientStop Color="White" Offset="0.0"/>
                <GradientStop Color="Green" Offset="1.0"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

绑定用户控件

我正在尝试将Binding绑定到值转换器返回的值。

Style="{DynamicResource ResourceKey={Binding Path=MonitoringType, Converter={StaticResource TSConverter}}}"

代码

MonitoringTypes Enum

public enum MonitoringTypes
{
    Running,
    Failed,
    Paused,
    Favorites,
}

用户控制

这里我要做的是将传入的MonitoringTypes枚举值的字符串值与一些众所周知的文本连接起来,以构建App.xaml中存在的样式名称。值转换器被称为 ,返回正确的值,但由于某种原因,样式不适用。

/// <summary>
/// Interaction logic for MonitorWorkflow.xaml
/// </summary>
public partial class MonitorWorkflow : UserControl
{
    public MonitorWorkflow(MonitoringTypes monitoringType)
    {
        InitializeComponent();

        this.DataContext = new MonitorWorkflowViewModel { MonitoringType = monitoringType };
    }
}

public class MonitorWorkflowViewModel
{
    public MonitoringTypes MonitoringType { get; set; }
}

public class TitleStyleValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var type = (MonitoringTypes)value;
        return string.Format("{0}TitleBlock", Enum.GetName(typeof(MonitoringTypes), type));
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return Enum.Parse(typeof(MonitoringTypes), value.ToString().Substring(0, value.ToString().IndexOf("TitleBlock")));
    }
}

2 个答案:

答案 0 :(得分:5)

我的建议是跳过DynamicResource声明并使用Converter直接提供Style

Style="{Binding Path=MonitoringType, Converter={StaticResource TSConverter}}"

TSConverter中,您可以返回Style而不是字符串。有点像这样:

public class TitleStyleValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, 
        System.Globalization.CultureInfo culture)
    {
        var type = (MonitoringTypes)value;
        var styleToReturn = FindResource(
            string.Format("{0}TitleBlock", 
                Enum.GetName(typeof(MonitoringTypes), type)));
        if (styleToReturn != null)
            return (Style)styleToReturn;
        else 
            return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        // not sure if you need this anymore... 
        return Enum.Parse(typeof(MonitoringTypes), value.ToString().Substring(0,
           value.ToString().IndexOf("TitleBlock")));
    }
}

这就是我所做的,但改为使用以下代码。实际上我在回答问题时回答了我自己的问题。好时机!

public class TitleStyleValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var type = (MonitoringTypes)value;
        return App.Current.Resources[string.Format("{0}TitleBlock", Enum.GetName(typeof(MonitoringTypes), type))];
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return Enum.Parse(typeof(MonitoringTypes), value.ToString().Substring(0, value.ToString().IndexOf("TitleBlock")));
    }
}

答案 1 :(得分:1)

public static Style DayModeButton = null; 

void loadStyle() 
{
Uri uri1 = new Uri("/Resources/ButtonStyle.xaml", UriKind.Relative);
                ResourceDictionary resDict1 = Application.LoadComponent(uri1) as ResourceDictionary;

foreach (object obj in resDict1.Values) //Set explicit reference
     if (obj is Style) DayModeButton = (Style)obj;
}



[ValueConversion(typeof(object), typeof(Style))]
public class GetStyleConverter: IValueConverter
{
         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
         {
               return DayModeButton ; 
         }
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
             return 0;
         }
}