Dynamic Style Binding with IValueConverter

我的梦境 提交于 2019-12-23 11:52:53

问题


I am trying to set a style, which is defined in the App.xaml, dynamically when loading a user control and it's just not applying the style for some reason (i.e. there is no error occurring, it's just not applying the style).

I'm sure it's because I've defined the binding wrong, but I'm unable to figure out what I need to do differently to get it to work.

App.xaml Style

The style I'm after is the RunningTitleBlock and it's comprised of a couple other styles that I've included in the below code sample.

<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 on the user control

I'm trying to get the Binding to bind to a value returned from a value converter.

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

Code

MonitoringTypes Enum

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

User Control

Here what I'm trying to do is concatenate the string value of the MonitoringTypes enum value that's passed in with some well known text to build a style name that exists in the App.xaml. The value converter is being called and returning the correct value, but for some reason the style isn't applying.

/// <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")));
    }
}

回答1:


My suggestion would be to skip the DynamicResource statement and using the Converter provide the Style directly.

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

In TSConverter, you can return a Style rather than a string. Kind of like this:

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")));
    }
}

This is what I did but with the following code instead. I actually just answered my own question while you answered it as well. Good timing!

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")));
    }
}



回答2:


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;
         }
}


来源:https://stackoverflow.com/questions/12060761/dynamic-style-binding-with-ivalueconverter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!