当源来自 x:Static resx 文件时,在样式中应用 ValueConverter
Apply ValueConverter in style when source comes from x:Static resx file
经过大量搜索和阅读其他问题和帖子后,我无法找到解决方法。注意:我对 WPF 比较陌生(一般不熟悉绑定)。
这是我想要的:
- 我想让 window 中的所有 TextBlock 控件以某种方式设置样式。
- 该样式还应应用 ValueConverter 以使文本全部大写。
- 最后,每个 TextBlock 文本可以来自绑定到视图模型 属性,或者来自绑定到 .resx 文件中的资源字符串
这是我正在玩的内容的摘录:
<!-- 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,但我不想将其应用于 window:
周围的所有 TextBlock
<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}}" />
尝试使用 'Label' 并构建模板,因为 '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" />
如果内容是纯文本(又名 'String'),则文本应始终为大写。
您的转换器无法正常工作,因为您的 TextBlock
正在覆盖 Style
的 Text
属性,其中包括您已添加到绑定中的转换器。
例如:
<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}"/>
希望您能从上面看到为什么您的方法不起作用。
更好的解决方案是在 TextBlock
上使用值转换器设置 Text
的值,而不是在 Style
上。
如果您不想这样做,可以使用一种常见的作弊方法来绕过此问题,可以将 TextBlock 的文本 属性 绑定到标签 属性,如下所示:
<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}"/>
我非常不喜欢这种方法,但它确实能满足您的需求。我希望您在 TextBlock
.
上设置绑定时只使用转换器
lukegv 的方法是另一种选择。但是,不需要使用 Label
,因为您正在覆盖模板并且(类似于我上面的示例)您只是绑定到 Content
属性 的 [=20] =].您可以从 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!"/>
不过我也不是特别喜欢这个想法,因为您无法访问所有其他 TextBlock
属性。比如我要设置我的TextBlock
的FontWeight
属性那我就被塞满了
经过大量搜索和阅读其他问题和帖子后,我无法找到解决方法。注意:我对 WPF 比较陌生(一般不熟悉绑定)。
这是我想要的:
- 我想让 window 中的所有 TextBlock 控件以某种方式设置样式。
- 该样式还应应用 ValueConverter 以使文本全部大写。
- 最后,每个 TextBlock 文本可以来自绑定到视图模型 属性,或者来自绑定到 .resx 文件中的资源字符串
这是我正在玩的内容的摘录:
<!-- 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,但我不想将其应用于 window:
周围的所有 TextBlock<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}}" />
尝试使用 'Label' 并构建模板,因为 '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" />
如果内容是纯文本(又名 'String'),则文本应始终为大写。
您的转换器无法正常工作,因为您的 TextBlock
正在覆盖 Style
的 Text
属性,其中包括您已添加到绑定中的转换器。
例如:
<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}"/>
希望您能从上面看到为什么您的方法不起作用。
更好的解决方案是在 TextBlock
上使用值转换器设置 Text
的值,而不是在 Style
上。
如果您不想这样做,可以使用一种常见的作弊方法来绕过此问题,可以将 TextBlock 的文本 属性 绑定到标签 属性,如下所示:
<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}"/>
我非常不喜欢这种方法,但它确实能满足您的需求。我希望您在 TextBlock
.
lukegv 的方法是另一种选择。但是,不需要使用 Label
,因为您正在覆盖模板并且(类似于我上面的示例)您只是绑定到 Content
属性 的 [=20] =].您可以从 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!"/>
不过我也不是特别喜欢这个想法,因为您无法访问所有其他 TextBlock
属性。比如我要设置我的TextBlock
的FontWeight
属性那我就被塞满了