我需要允许选择只读屏幕中显示的文本。
我们的一位开发人员提出的一个简单解决方案是使用 TextBox
而不是 Label 或 TextBlock,其样式如下:
<Style x:Key="ControlData" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="TextWrapping" Value="Wrap" />
<!-- unrelated properties ommitted -->
</Style>
我不喜欢在那里使用文本框的想法,因为它迫使我使用Binding Mode=OneWay
作为只读属性,所以我试图定义一个样式我可以将其应用于标签以获得相同的结果:
<Style x:Key="SelectableLabel" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<TextBox Style="{StaticResource ControlData}"
Text="{Binding Path=Content, Mode=OneWay,
RelativeSource={RelativeSource FindAncestor,
AncestorType=Label}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
问题是,我的一些绑定(bind)设置了 StringFormat
,但它丢失了。
- 有办法保持外部绑定(bind)的格式吗?
- 我应该以不同的方式创建模板/绑定(bind)吗?
- 还有比这更好的完全不同的方法吗?
- 我应该停止挑剔并使用 TextBox 吗?
最佳答案
我认为使用标签并覆盖控件模板是个好主意。最后,这就是 WPF 中控制逻辑和布局分离的目的,您应该利用它来获得更清晰、更易于理解的 xaml 代码。
您是否尝试使用 TemplateBinding 代替普通 Binding?我不确定这是否会保留外部绑定(bind),但这是建议在 DataTemplates 中使用的绑定(bind)。
您还应该看看 ContentPresenter 类,尽管我不确定它是否适用于此,因为您的内部文本框只有一个字符串类型的 Text 属性...
编辑: 我解决了这个问题,尽管它比我想象的要复杂......
创建样式如下:
<Application.Resources>
<LabelTest:ContentToTextConverter x:Key="contentConverter" />
<Style TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<TextBox DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource FindAncestor,AncestorType=Label}}">
<TextBox.Text>
<MultiBinding Converter="{StaticResource contentConverter}" >
<Binding Mode="OneWay" Path="ContentStringFormat" />
<Binding Mode="OneWay" Path="Content" />
</MultiBinding>
</TextBox.Text>
</TextBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
ContentToTextConverter 定义如下:
public class ContentToTextConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var format = values[0] as string;
if (string.IsNullOrEmpty(format)) format = "{0}";
else if(format.IndexOf('{') < 0) format = "{0:" + format + "}";
return string.Format(culture, format, values[1]);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
使用示例:
<Label ContentStringFormat="{}{0}$">
<System:Int64>15</System:Int64>
</Label>
如果能找到比这更好的解决方案就好了,但目前它应该可以按预期工作。
关于wpf - 尝试创建允许文本选择的 WPF 标签模板时出现格式问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5939322/