wpf - 尝试创建允许文本选择的 WPF 标签模板时出现格式问题

标签 wpf data-binding styles controltemplate

我需要允许选择只读屏幕中显示的文本。

我们的一位开发人员提出的一个简单解决方案是使用 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/

相关文章:

python - tkinter checkbutton 不同的图像

css - 使用 styleUrls 在 AngularJS2 中导入样式

C# WPF 使工具栏在工具栏托盘内右对齐

WPF 通过绑定(bind)隐藏 DataGridColumn

c# - 在 WPF 中将 IsEnabled 绑定(bind)到 IsChecked

javascript - Knockout JS 入门

asp.net - 将 <a> href 绑定(bind)到 Code Behind 属性

c# - FocusManager.FocusedElement 在菜单中不起作用

c# - 无法更新,因为没有主键

android - 值(value)子文件夹内的样式资源