将文本添加到System.Windows.Shapes.Shape代码后面,

时间:2017-03-16 10:47:47

标签: c# wpf text shapes

我需要将Text作为System.Window.Shapes Shape返回(不要问为什么,它的任务)。由于没有Text-Shape,我想我可以将一个Text添加到一个透明的Rectangle中,但事实证明,我在网上发现的所有东西,生成的文本看起来并不好看,但更糟糕的是:它用一些讨厌的人工制品:

看起来像文本的上部顶部被剪切并附加在底部(就像文本溢出一样)

这就是我做的方式(Need to add text to rectangle):

  Rectangle r = new Rectangle();
  r.Stroke = Brushes.Transparent;
  r.StrokeThickness = 1;
  r.VerticalAlignment = VerticalAlignment.Top;
  r.HorizontalAlignment = HorizontalAlignment.Left;
  r.Margin = new Thickness(0);
  r.Width = 200;
  r.Height = 200;
  r.RenderTransform = new TranslateTransform(100, 100);
  TextBlock TB = new TextBlock();
  TB.Text = "TEST";
  var ft = new FormattedText(
               TB.Text,
               CultureInfo.CurrentCulture,
               FlowDirection.LeftToRight,
               new Typeface("Verdana"),
               16,
               Brushes.Black);
  r.Width = ft.Width;
  r.Height = ft.Height;
  //The next two magical lines create a special brush that contains a bitmap rendering of the UI element that can then be used like any other brush and its in hardware and is almost the text book example for utilizing all hardware rending performances in WPF unleashed 4.5
  BitmapCacheBrush bcb = new BitmapCacheBrush(TB);
  r.Fill = bcb;

有人可以解释为什么会发生这种情况并提供解决方法吗?尝试使用厚度,填充等,但它没有给出所需的结果。 我将不胜感激任何帮助!谢谢你

2 个答案:

答案 0 :(得分:1)

使用MVVM和datatemplates很容易实现您想要的功能。下面是一个简化的演示,为您提供想法。

XAML:

<ItemsControl ItemsSource="{Binding Items}">
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:TextItem}">
            <TextBlock Text="{Binding Text}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:ShapeItem}">
            <ContentControl Content="{Binding Shape}" />
        </DataTemplate>
    </ItemsControl.Resources>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="ContentPresenter">
            <Setter Property="Canvas.Left" Value="{Binding Left}" />
            <Setter Property="Canvas.Top" Value="{Binding Top}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

CS:

public class Item
{
    public double Left { get; set; }
    public double Top { get; set; }
}

public class ShapeItem : Item
{
    public Shape Shape { get; set; }
}

public class TextItem : Item
{
    public string Text { get; set; }
}

public partial class MainWindow : Window
{
    public List<object> Items { get; } = new List<object>
    {
        new ShapeItem { Shape = new Rectangle { Width = 100, Height = 100, Fill= Brushes.Yellow, Stroke = Brushes.Red }, Left = 10, Top = 10 },
        new TextItem { Text= "Lalala", Left = 50, Top = 50 },
    };

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }
}

这是输出:

它不是100%MVVM(为了简单起见),但想法是为文本和形状提供不同的数据模板。它们具有不同的视图模型:TextItemShapeItem,并相应地显示为TextBlockContentControl

另一件事是使用ItemsControl能够绑定到Items的集合并设置Canvas.Left/Canvas.Top属性。

ToDo:使用ObservableCollection,为viewmodel实现INotifyPropertyChanged,不要在viewmodel中使用视图元素(画笔,形状等)。

答案 1 :(得分:0)

尽管我很感谢所有答案,但我找到了解决方案:

只需将Textblock的fontsize设置为您在formattedText中使用的相同大小即可计算Text width和Height:

tb.Fontsize = 16; ...

这样不仅文本&#34;溢出&#34;消失,但文字看起来很漂亮