【问题标题】:Binding a property to a style/resourcedictionary of a view将属性绑定到视图的样式/资源字典
【发布时间】:2012-08-28 22:30:04
【问题描述】:

我的一个视图由 5 个UserControls 组成,每个视图都显示有关某个对象的数据。例如,假设视图显示了我们公司拥有的奶牛,并且在屏幕上显示了奶牛 1 到 5(每个都在自己的 UserControl 中)。

我想做的(但不确定是否可能)是将牛的状态绑定到其各自的 UserControl 中使用的样式。所以我们有一个属性status,例如可以是okhungrydead。如果奶牛是ok,我想显示“正常”样式,如果是hungry,我希望背景为红色,如果是dead,我希望文本为黑色并增加字体大小。

我添加了我想要实现的简化版本。不过,我对 WPF 样式/资源字典的了解仍然有限。

我基本上想要的代码
具有 Status 属性的 ViewModel

class CowInfoViewModel : Screen
{
    public string Name { get; set; }

    public string Status { get; set; } //"ok", "hungry", "dead"
}

检索样式或资源字典的视图

<UserControl x:Class="WpfModifyDifferentView.Views.CowInfoView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <!-- A reference to a ResourceDictionary with styles, that is bound to the 'Status' property -->

    <StackPanel>
        <TextBlock x:Name="Name" Text="Cow Name"/>
        <TextBlock x:Name="Status" Text="Ok" />
    </StackPanel>
</UserControl>

编辑 - 解决方案:

我使用 Vale 的回答做了以下事情:

在xaml中(引用转换器):

    <UserControl.Resources>
        <Converters:CowStyleConverter x:Key="styleConverter" />
    </UserControl.Resources>

在xaml(元素)中:

        <TextBlock x:Name="Name" Text="Cow Name" Style="{Binding Path=Style, ConverterParameter='TextBlockCowName', Converter={StaticResource styleConverter}}" />

转换器(注意我省略了检查):

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var status = value.ToString();
        var styleName = parameter.ToString();

        _resourceDictionary.Source = new System.Uri(string.Format("pack://application:,,,/Resources/ScreenI2Style{0}.xaml", status));

        return _resourceDictionary[styleName];
    }

然后我创建了多个 ResourceDictionaries,其样式如下:

<Style x:Key="TextBlockCowName" TargetType="TextBlock">
    <Setter Property="Foreground" Value="{StaticResource SomeBrush}" />
</Style>

【问题讨论】:

    标签: c# wpf caliburn.micro


    【解决方案1】:

    您可以将 UserControl Style 属性绑定到 Status 并使用转换器。

    <UserControl x:Class="WpfModifyDifferentView.Views.CowInfoView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                 xmlns:local="clr-namespace:WpfModifyDifferentView"
                 Style="{Binding Path=Status, Converter={StaticResource myConverter}}">
            <UserControl.Resources>
                <local:MyConverter x:Key="myConverter" />
            </UserControl.Resources>
    

    我假设您的转换器直接在 WpfModifyDifferentView 中。 转换器将如下所示:

    public class MyConverter : IValueConverter {
            private ResourceDictionary dictionary;
    
            public MyConverter() {
                if (dictionary == null) {
                    dictionary = new ResourceDictionary();
                    dictionary.Source = new Uri("pack://application:,,,/WpfModifyDifferentView;Component/Resources/Styles.xaml");
                }
            }
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
                switch (value.ToString()) {
                    case "ok":
                        return dictionary["myKeyForOkStyle"] as Style;
                    case "hungry":
                        return dictionary["myKeyForHungryStyle"] as Style;
                    case "dead":
                        return dictionary["myKeyForDeadStyle"] as Style;
                    default:
                        return null;
                }
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
                throw new NotImplementedException();
            }
        }
    

    您当然需要指定正确的 URI。

    【讨论】:

    • 感谢您的回答 :) 目前在我工作的地方出现了一些其他问题。我会尽快试试这个
    • 再次感谢您的回答,我刚刚尝试过,效果很好:) 我只是想知道是否可以更改多个元素的样式? (对于某些特定元素,样式总是有 TargetType 吗?)例如,我想升级 UserControl、Grid、Borders 和 TextBlocks,但是(afaik)每个都需要不同的样式元素。这是否意味着我必须在 Status 案例中添加一个额外的 switch 语句才能获得相应样式的元素?
    • 是的,如果您针对该类型执行特定操作,则需要不同的样式。但是,如果您想更改常规(基本)属性,您可以将 TargetType 设置为 Control 或 FrameworkElement,例如。是的,如果你想在不同风格的不同类型上使用相同的转换器,你可以在 switch 语句中检查 targetType 参数。
    • 通过在 xaml 中设置 Path(状态)和 ConverterParameter(样式名称)使其工作。我会稍微更新一下我的问题以显示结果,再次感谢!
    猜你喜欢
    • 2012-04-02
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多