2011-05-09 64 views
3

我有一个要求,允许选择在只读屏幕显示的文字。格式问题试图创建一个WPF标签模板,让文本选择

我们开发一个简单的解决一个想出了使用TextBox而不是标签或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> 

我不喜欢使用一个TextBox存在的想法,除其他事项外,因为它迫使我使用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> 

的问题是,一些我的绑定有StringFormat集,那就是迷路了。

  • 有没有办法保持外部绑定的格式?
  • 我应该创建我的模板/装订不同?
  • 有一个完全不同的做法,是比这更好的?
  • 我应该停止与挑剔和与文本框去?
+0

@wangburger:你是什么意思? – 2011-05-09 15:59:51

+0

使用“TextBox”有什么问题?你到目前为止所说的只是你不喜欢它。为什么? – 2011-05-09 16:23:34

+0

@RobertRossney:因为TextBox是一个**输入**元素,为其设置了基础结构,而不是用于只读显示。这也迫使我添加'Mode = OneWay'到我的所有绑定中,而无需setter。 – 2011-05-09 16:38:26

回答

2

我认为使用标签并覆盖控件模板是个不错的主意。最后,这是WPF中控制逻辑和布局的分离,您应该利用它来获得更清晰,更容易理解的xaml代码。

你有没有尝试使用正常绑定的TemplateBinding instad?我不确定这是否会保留外部绑定,但是它是DataTemplates中使用的推荐绑定。

你也应该看看的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> 

这将是很好找到比这一个更好的解决方案,但目前预期它应该工作。

+0

我尝试了{TemplateBinding内容}没有结果(文本是空的)和ContentPresenter (同上) – 2011-05-10 11:06:28

+0

这看起来不错。我会试一试并接受它是否有效。 – 2011-05-13 14:22:56

2

我应该停止与挑剔和与文本框去?

当然。

+0

这是有点我最后的选择,但我会这样做,如果它是唯一的方法:-) – 2011-05-09 16:00:44