源来自x:Static resx文件时,应用ValueConverter

时间:2015-01-21 13:31:27

标签: wpf xaml ivalueconverter wpf-style

经过一番搜索和阅读其他问题&帖子,我无法找到如何解决这个问题。注意:我对WPF来说相对较新(不是一般的绑定)。

这是我之后的事情:

  1. 我希望窗口中的所有TextBlock控件都能以某种方式进行样式设置。
  2. 该样式还应该应用ValueConverter使文本全部为大写。
  3. 最后,每个TextBlock Text可以来自绑定到视图模型属性,也可以绑定到.resx文件中的资源字符串
  4. 这是我正在玩的内容的摘录:

    <!-- in Window resources -->
    <help:AllCapsStringConverter x:Key="AllCaps"/>
    
    <Style TargetType="TextBlock">
        <Setter Property="Foreground" Value="Brown" />
        <Setter Property="Text">
            <Setter.Value>
                <Binding>
                    <Binding.Converter>
                        <help:AllCapsStringConverter />
                    </Binding.Converter>
                    <!-- also tried adding:
                    <Binding.RelativeSource>
                        <RelativeSource Mode="Self" />
                    </Binding.RelativeSource>
                    -->
                </Binding>
    
                <!-- also tried with: 
                <Binding Converter="{StaticResource AllCaps}"/>
    
                <Binding Path="Text" Converter="{StaticResource AllCaps}"/>
                -->
            </Setter.Value>
        </Setter>
    </Style>
    
    <!-- in Window content -->
    <TextBlock Text="{x:Static resx:MyResources.MyTitle}" />
    

    这里是值转换器,它本身已证明有效:

    class AllCapsStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null && value is string)
            {
                return ((string)value).ToUpper();
            }
            else
            {
                return value;
            }
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
    

    TextBlocks获取前景色,但没有转换。

    我能够将转换器本地应用到单个TextBlock,但我不想将其应用于窗口周围的所有TextBlocks:

    <TextBlock>
        <TextBlock.Text>
            <Binding Source="{x:Static resx:MyResources.MyTitle}"
                     Converter="{StaticResource AllCaps}"/>
        </TextBlock.Text>
    </TextBlock>
    <!-- which is the same as -->
    <TextBlock Style="{StaticResource CustomerInfoTitleStyle}" 
               Text="{Binding Source={x:Static resx:MyResources.MyTitle}, Converter={StaticResource AllCaps}}" />
    

2 个答案:

答案 0 :(得分:1)

您的转换器无效,因为TextBlock覆盖了Text的{​​{1}}属性,其中包含您已添加到绑定中的转换器。

例如:

Style

希望从上面你可以看出为什么你的方法不起作用。

更好的解决方案是将<Grid.Resources> <Style x:Key="MyTextBlockStyle" TargetType="TextBlock"> <Setter Property="Foreground" Value="Red"/> <Setter Property="FontSize" Value="16"/> <Setter Property="Text" Value="You won't see this."></Setter> </Style> </Grid.Resources> <TextBlock Text="You will see this." Style="{StaticResource MyTextBlockStyle}"/> 的值设置为Text上的值转换器,而不是TextBlock

如果您不想这样做,可以使用一个常见的作法来解决这个问题,可能是将TextBlock的Text属性绑定到Tag属性,如下所示:

Style

我非常不喜欢这种方法,但它确实能让你得到你想要的东西。我希望您在<Grid.Resources> <local:AllCapsConverter x:Key="AllCaps"/> <Style x:Key="MyTextBlockStyle" TargetType="TextBlock"> <Setter Property="Foreground" Value="Red"/> <Setter Property="FontSize" Value="16"/> <Setter Property="Text" Value="{Binding Tag, RelativeSource={RelativeSource Self}, Converter={StaticResource AllCaps}}"/> </Style> </Grid.Resources> <TextBlock Tag="You will see this." Style="{StaticResource MyTextBlockStyle}"/> 上设置绑定时使用转换器。

lukegv的方法是另一种选择。但是,没有必要使用TextBlock,因为您要覆盖模板并且(与上面的示例类似)您只是绑定到Label的{​​{1}}属性。您可以从Content轻松获得所需内容。

Label

我不是这个想法的特别忠实粉丝,因为你失去了对所有其他ContentControl属性的访问权限。例如,如果我想设置<Grid.Resources> <local:AllCapsConverter x:Key="AllCaps"/> <Style x:Key="MyContentControl" TargetType="ContentControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <TextBlock Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource AllCaps}}"/> </ControlTemplate> </Setter.Value> </Setter> </Style> </Grid.Resources> <ContentControl Style="{StaticResource MyContentControl}" Content="You will see this too!"/> 的{​​{1}}属性,那么我就会被填充。

答案 1 :(得分:0)

尝试使用'标签'并构建模板,因为'TextBlock' is not a control

<Style x:Key="AllCapsLabel" TargetType="{x:Type Label}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Label">
                <TextBlock Foreground="Brown" Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource AllCaps}}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

并以这种方式使用它:

<Label Style="{StaticResource AllCapsLabel}" Content="whatever you want" />

如果内容是纯文本(又称“字符串”),则文本应始终为大写。