【问题标题】:Dynamic Style Binding with IValueConverter使用 IValueConverter 进行动态样式绑定
【发布时间】:2012-08-21 18:20:04
【问题描述】:

我正在尝试在加载用户控件时动态设置在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 枚举

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

【问题讨论】:

  • 我可能只使用 IValueConverter 并返回样式。
  • 您绑定的属性必须是依赖属性,或者您需要实现 INotifyPropertyChanged 以在值更新时通知绑定。在您的情况下,您需要在枚举值更改时通知您的“TitleBlockStyle”属性已更改(将其包装在属性中)。您最好使用 ValueConverter 并将其绑定到您的枚举,如下例所示:stackoverflow.com/questions/5082509/…
  • @patrickinmpls,我已经更新了我的问题以显示我尝试在哪里使用值转换器。
  • @Moozhe,我已经更新了我的问题以显示我尝试在哪里使用值转换器。
  • @code4life,所以你想看看如果我不尝试继承,是否只​​有 Background 被应用?

标签: wpf custom-controls


【解决方案1】:

我的建议是跳过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")));
    }
}

【讨论】:

  • @Mike,我对您的代码进行了更多思考,想知道您是否想查看DataTriggers 来强制执行样式而不是这种方法。这就是我一直在为您正在采用的样式方法做的事情。
  • 我认为你是对的 - 这更简洁。我可以构建一种样式,在Style 上为Label 做一个简单的StaticResource 绑定,然后使用DataTrigger 来切换样式。
【解决方案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;
         }
}

【讨论】:

  • 可能是评论或其他内容来解释您的代码 :)
猜你喜欢
  • 2013-11-15
  • 1970-01-01
  • 2017-05-27
  • 1970-01-01
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多