2016-03-27 132 views
1

我想垂直写入边框元素内的文本。如图所示。带有XAML的UWP应用程序中的垂直文本

Vertical Text

我使用的RenderTransform与此代码

<Border Width="80" 
 
     Background="Teal"> 
 
    <TextBlock Text="CATEGORIES" 
 
      Foreground="White" 
 
      FontFamily="Segoe UI Black" 
 
      FontSize="30"> 
 
    <TextBlock.RenderTransform> 
 
     <RotateTransform Angle="-90" /> 
 
    </TextBlock.RenderTransform> 
 
    </TextBlock> 
 
</Border>

这个垂直旋转文本尝试,但TextBlock的需要的高度和宽度的旧值之前变换不完整地显示文本。所以文字在80像素(边框元素的宽度)之后被切断。虽然搜索我发现使用LayoutTransform可以解决这个问题,但它不适用于UWP应用程序。如何在UWP XAML中执行此操作?

+0

'RenderTransform'不仅影响外观,它不会神奇地改变布局添加命名空间像'Width'或'Height'这些属性永远不会反映变换的结果。 –

回答

10

This也在UWP上为我工作。只需使用发布的帖子here而不是帖子中的帖子。并且从博客文章中复制样式。


编辑:onedrive链接不再起作用。所以我在这里发布代码。

创建一个新类LayoutTransformer

using System; 
using System.Diagnostics.CodeAnalysis; 
using Windows.Foundation; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Media; 

namespace Common 
{ 
    /// <summary> 
    /// Represents a control that applies a layout transformation to its Content. 
    /// </summary> 
    /// <QualityBand>Preview</QualityBand> 
    [TemplatePart(Name = TransformRootName, Type = typeof(Grid))] 
    [TemplatePart(Name = PresenterName, Type = typeof(ContentPresenter))] 
    public sealed class LayoutTransformer : ContentControl 
    { 
     /// <summary> 
     /// Name of the TransformRoot template part. 
     /// </summary> 
     private const string TransformRootName = "TransformRoot"; 

     /// <summary> 
     /// Name of the Presenter template part. 
     /// </summary> 
     private const string PresenterName = "Presenter"; 

     /// <summary> 
     /// Gets or sets the layout transform to apply on the LayoutTransformer 
     /// control content. 
     /// </summary> 
     /// <remarks> 
     /// Corresponds to UIElement.LayoutTransform. 
     /// </remarks> 
     public Transform LayoutTransform 
     { 
      get { return (Transform)GetValue(LayoutTransformProperty); } 
      set { SetValue(LayoutTransformProperty, value); } 
     } 

     /// <summary> 
     /// Identifies the LayoutTransform DependencyProperty. 
     /// </summary> 
     public static readonly DependencyProperty LayoutTransformProperty = DependencyProperty.Register(
      "LayoutTransform", typeof(Transform), typeof(LayoutTransformer), new PropertyMetadata(null, LayoutTransformChanged)); 

     /// <summary> 
     /// Gets the child element being transformed. 
     /// </summary> 
     private FrameworkElement Child 
     { 
      get 
      { 
       // Preferred child is the content; fall back to the presenter itself 
       return (null != _contentPresenter) ? 
        (_contentPresenter.Content as FrameworkElement ?? _contentPresenter) : 
        null; 
      } 
     } 

     // Note: AcceptableDelta and DecimalsAfterRound work around double arithmetic rounding issues on Silverlight. 

     private const double AcceptableDelta = 0.0001; 

     private const int DecimalsAfterRound = 4; 

     private Panel _transformRoot; 

     private ContentPresenter _contentPresenter; 

     private MatrixTransform _matrixTransform; 

     private Matrix _transformation; 

     private Size _childActualSize = Size.Empty; 

     public LayoutTransformer() 
     { 
      // Associated default style 
      DefaultStyleKey = typeof(LayoutTransformer); 

      // Can't tab to LayoutTransformer 
      IsTabStop = false; 
#if SILVERLIGHT 
      // Disable layout rounding because its rounding of values confuses things 
      UseLayoutRounding = false; 
#endif 
     } 

     /// <summary> 
     /// Builds the visual tree for the LayoutTransformer control when a new 
     /// template is applied. 
     /// </summary> 
     protected override void OnApplyTemplate() 
     { 
      // Apply new template 
      base.OnApplyTemplate(); 
      // Find template parts 
      _transformRoot = GetTemplateChild(TransformRootName) as Grid; 
      _contentPresenter = GetTemplateChild(PresenterName) as ContentPresenter; 
      _matrixTransform = new MatrixTransform(); 
      if (null != _transformRoot) 
      { 
       _transformRoot.RenderTransform = _matrixTransform; 
      } 
      // Apply the current transform 
      ApplyLayoutTransform(); 
     } 

     /// <summary> 
     /// Handles changes to the Transform DependencyProperty. 
     /// </summary> 
     /// <param name="o">Source of the change.</param> 
     /// <param name="e">Event args.</param> 
     private static void LayoutTransformChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
     { 
      // Casts are safe because Silverlight is enforcing the types 
      ((LayoutTransformer)o).ProcessTransform((Transform)e.NewValue); 
     } 

     /// <summary> 
     /// Applies the layout transform on the LayoutTransformer control content. 
     /// </summary> 
     /// <remarks> 
     /// Only used in advanced scenarios (like animating the LayoutTransform). 
     /// Should be used to notify the LayoutTransformer control that some aspect 
     /// of its Transform property has changed. 
     /// </remarks> 
     public void ApplyLayoutTransform() 
     { 
      ProcessTransform(LayoutTransform); 
     } 

     /// <summary> 
     /// Processes the Transform to determine the corresponding Matrix. 
     /// </summary> 
     /// <param name="transform">Transform to process.</param> 
     private void ProcessTransform(Transform transform) 
     { 
      // Get the transform matrix and apply it 
      _transformation = RoundMatrix(GetTransformMatrix(transform), DecimalsAfterRound); 
      if (null != _matrixTransform) 
      { 
       _matrixTransform.Matrix = _transformation; 
      } 
      // New transform means re-layout is necessary 
      InvalidateMeasure(); 
     } 

     /// <summary> 
     /// Walks the Transform(Group) and returns the corresponding Matrix. 
     /// </summary> 
     /// <param name="transform">Transform(Group) to walk.</param> 
     /// <returns>Computed Matrix.</returns> 
     private Matrix GetTransformMatrix(Transform transform) 
     { 
      if (null != transform) 
      { 
       // WPF equivalent of this entire method: 
       // return transform.Value; 

       // Process the TransformGroup 
       TransformGroup transformGroup = transform as TransformGroup; 
       if (null != transformGroup) 
       { 
        Matrix groupMatrix = Matrix.Identity; 
        foreach (Transform child in transformGroup.Children) 
        { 
         groupMatrix = MatrixMultiply(groupMatrix, GetTransformMatrix(child)); 
        } 
        return groupMatrix; 
       } 

       // Process the RotateTransform 
       RotateTransform rotateTransform = transform as RotateTransform; 
       if (null != rotateTransform) 
       { 
        double angle = rotateTransform.Angle; 
        double angleRadians = (2 * Math.PI * angle)/360; 
        double sine = Math.Sin(angleRadians); 
        double cosine = Math.Cos(angleRadians); 
        return new Matrix(cosine, sine, -sine, cosine, 0, 0); 
       } 

       // Process the ScaleTransform 
       ScaleTransform scaleTransform = transform as ScaleTransform; 
       if (null != scaleTransform) 
       { 
        double scaleX = scaleTransform.ScaleX; 
        double scaleY = scaleTransform.ScaleY; 
        return new Matrix(scaleX, 0, 0, scaleY, 0, 0); 
       } 

       // Process the SkewTransform 
       SkewTransform skewTransform = transform as SkewTransform; 
       if (null != skewTransform) 
       { 
        double angleX = skewTransform.AngleX; 
        double angleY = skewTransform.AngleY; 
        double angleXRadians = (2 * Math.PI * angleX)/360; 
        double angleYRadians = (2 * Math.PI * angleY)/360; 
        return new Matrix(1, angleYRadians, angleXRadians, 1, 0, 0); 
       } 

       // Process the MatrixTransform 
       MatrixTransform matrixTransform = transform as MatrixTransform; 
       if (null != matrixTransform) 
       { 
        return matrixTransform.Matrix; 
       } 

       // TranslateTransform has no effect in LayoutTransform 
      } 

      // Fall back to no-op transformation 
      return Matrix.Identity; 
     } 

     /// <summary> 
     /// Provides the behavior for the "Measure" pass of layout. 
     /// </summary> 
     /// <param name="availableSize">The available size that this element can give to child elements.</param> 
     /// <returns>The size that this element determines it needs during layout, based on its calculations of child element sizes.</returns> 
     protected override Size MeasureOverride(Size availableSize) 
     { 
      FrameworkElement child = Child; 
      if ((null == _transformRoot) || (null == child)) 
      { 
       // No content, no size 
       return Size.Empty; 
      } 

      //DiagnosticWriteLine("MeasureOverride < " + availableSize); 
      Size measureSize; 
      if (_childActualSize == Size.Empty) 
      { 
       // Determine the largest size after the transformation 
       measureSize = ComputeLargestTransformedSize(availableSize); 
      } 
      else 
      { 
       // Previous measure/arrange pass determined that Child.DesiredSize was larger than believed 
       //DiagnosticWriteLine(" Using _childActualSize"); 
       measureSize = _childActualSize; 
      } 

      // Perform a mesaure on the _transformRoot (containing Child) 
      //DiagnosticWriteLine(" _transformRoot.Measure < " + measureSize); 
      _transformRoot.Measure(measureSize); 
      //DiagnosticWriteLine(" _transformRoot.DesiredSize = " + _transformRoot.DesiredSize); 

      // WPF equivalent of _childActualSize technique (much simpler, but doesn't work on Silverlight 2) 
      // // If the child is going to render larger than the available size, re-measure according to that size 
      // child.Arrange(new Rect()); 
      // if (child.RenderSize != child.DesiredSize) 
      // { 
      //  _transformRoot.Measure(child.RenderSize); 
      // } 

      // Transform DesiredSize to find its width/height 
      Rect transformedDesiredRect = RectTransform(new Rect(0, 0, _transformRoot.DesiredSize.Width, _transformRoot.DesiredSize.Height), _transformation); 
      Size transformedDesiredSize = new Size(transformedDesiredRect.Width, transformedDesiredRect.Height); 

      // Return result to allocate enough space for the transformation 
      //DiagnosticWriteLine("MeasureOverride > " + transformedDesiredSize); 
      return transformedDesiredSize; 
     } 

     /// <summary> 
     /// Provides the behavior for the "Arrange" pass of layout. 
     /// </summary> 
     /// <param name="finalSize">The final area within the parent that this element should use to arrange itself and its children.</param> 
     /// <returns>The actual size used.</returns> 
     /// <remarks> 
     /// Using the WPF paramater name finalSize instead of Silverlight's finalSize for clarity 
     /// </remarks> 
     protected override Size ArrangeOverride(Size finalSize) 
     { 
      FrameworkElement child = Child; 
      if ((null == _transformRoot) || (null == child)) 
      { 
       // No child, use whatever was given 
       return finalSize; 
      } 

      //DiagnosticWriteLine("ArrangeOverride < " + finalSize); 
      // Determine the largest available size after the transformation 
      Size finalSizeTransformed = ComputeLargestTransformedSize(finalSize); 
      if (IsSizeSmaller(finalSizeTransformed, _transformRoot.DesiredSize)) 
      { 
       // Some elements do not like being given less space than they asked for (ex: TextBlock) 
       // Bump the working size up to do the right thing by them 
       //DiagnosticWriteLine(" Replacing finalSizeTransformed with larger _transformRoot.DesiredSize"); 
       finalSizeTransformed = _transformRoot.DesiredSize; 
      } 
      //DiagnosticWriteLine(" finalSizeTransformed = " + finalSizeTransformed); 

      // Transform the working size to find its width/height 
      Rect transformedRect = RectTransform(new Rect(0, 0, finalSizeTransformed.Width, finalSizeTransformed.Height), _transformation); 
      // Create the Arrange rect to center the transformed content 
      Rect finalRect = new Rect(
       -transformedRect.Left + ((finalSize.Width - transformedRect.Width)/2), 
       -transformedRect.Top + ((finalSize.Height - transformedRect.Height)/2), 
       finalSizeTransformed.Width, 
       finalSizeTransformed.Height); 

      // Perform an Arrange on _transformRoot (containing Child) 
      //DiagnosticWriteLine(" _transformRoot.Arrange < " + finalRect); 
      _transformRoot.Arrange(finalRect); 
      //DiagnosticWriteLine(" Child.RenderSize = " + child.RenderSize); 

      // This is the first opportunity under Silverlight to find out the Child's true DesiredSize 
      if (IsSizeSmaller(finalSizeTransformed, child.RenderSize) && (Size.Empty == _childActualSize)) 
      { 
       // Unfortunately, all the work so far is invalid because the wrong DesiredSize was used 
       //DiagnosticWriteLine(" finalSizeTransformed smaller than Child.RenderSize"); 
       // Make a note of the actual DesiredSize 
       _childActualSize = new Size(child.ActualWidth, child.ActualHeight); 
       //DiagnosticWriteLine(" _childActualSize = " + _childActualSize); 
       // Force a new measure/arrange pass 
       InvalidateMeasure(); 
      } 
      else 
      { 
       // Clear the "need to measure/arrange again" flag 
       _childActualSize = Size.Empty; 
      } 
      //DiagnosticWriteLine(" _transformRoot.RenderSize = " + _transformRoot.RenderSize); 

      // Return result to perform the transformation 
      //DiagnosticWriteLine("ArrangeOverride > " + finalSize); 
      return finalSize; 
     } 

     /// <summary> 
     /// Compute the largest usable size (greatest area) after applying the transformation to the specified bounds. 
     /// </summary> 
     /// <param name="arrangeBounds">Arrange bounds.</param> 
     /// <returns>Largest Size possible.</returns> 
     [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Closely corresponds to WPF's FrameworkElement.FindMaximalAreaLocalSpaceRect.")] 
     private Size ComputeLargestTransformedSize(Size arrangeBounds) 
     { 
      //DiagnosticWriteLine(" ComputeLargestTransformedSize < " + arrangeBounds); 

      // Computed largest transformed size 
      Size computedSize = Size.Empty; 

      // Detect infinite bounds and constrain the scenario 
      bool infiniteWidth = double.IsInfinity(arrangeBounds.Width); 
      if (infiniteWidth) 
      { 
       arrangeBounds.Width = arrangeBounds.Height; 
      } 
      bool infiniteHeight = double.IsInfinity(arrangeBounds.Height); 
      if (infiniteHeight) 
      { 
       arrangeBounds.Height = arrangeBounds.Width; 
      } 

      // Capture the matrix parameters 
      double a = _transformation.M11; 
      double b = _transformation.M12; 
      double c = _transformation.M21; 
      double d = _transformation.M22; 

      // Compute maximum possible transformed width/height based on starting width/height 
      // These constraints define two lines in the positive x/y quadrant 
      double maxWidthFromWidth = Math.Abs(arrangeBounds.Width/a); 
      double maxHeightFromWidth = Math.Abs(arrangeBounds.Width/c); 
      double maxWidthFromHeight = Math.Abs(arrangeBounds.Height/b); 
      double maxHeightFromHeight = Math.Abs(arrangeBounds.Height/d); 

      // The transformed width/height that maximize the area under each segment is its midpoint 
      // At most one of the two midpoints will satisfy both constraints 
      double idealWidthFromWidth = maxWidthFromWidth/2; 
      double idealHeightFromWidth = maxHeightFromWidth/2; 
      double idealWidthFromHeight = maxWidthFromHeight/2; 
      double idealHeightFromHeight = maxHeightFromHeight/2; 

      // Compute slope of both constraint lines 
      double slopeFromWidth = -(maxHeightFromWidth/maxWidthFromWidth); 
      double slopeFromHeight = -(maxHeightFromHeight/maxWidthFromHeight); 

      if ((0 == arrangeBounds.Width) || (0 == arrangeBounds.Height)) 
      { 
       // Check for empty bounds 
       computedSize = new Size(arrangeBounds.Width, arrangeBounds.Height); 
      } 
      else if (infiniteWidth && infiniteHeight) 
      { 
       // Check for completely unbound scenario 
       computedSize = new Size(double.PositiveInfinity, double.PositiveInfinity); 
      } 
      else if (!MatrixHasInverse(_transformation)) 
      { 
       // Check for singular matrix 
       computedSize = new Size(0, 0); 
      } 
      else if ((0 == b) || (0 == c)) 
      { 
       // Check for 0/180 degree special cases 
       double maxHeight = (infiniteHeight ? double.PositiveInfinity : maxHeightFromHeight); 
       double maxWidth = (infiniteWidth ? double.PositiveInfinity : maxWidthFromWidth); 
       if ((0 == b) && (0 == c)) 
       { 
        // No constraints 
        computedSize = new Size(maxWidth, maxHeight); 
       } 
       else if (0 == b) 
       { 
        // Constrained by width 
        double computedHeight = Math.Min(idealHeightFromWidth, maxHeight); 
        computedSize = new Size(
         maxWidth - Math.Abs((c * computedHeight)/a), 
         computedHeight); 
       } 
       else if (0 == c) 
       { 
        // Constrained by height 
        double computedWidth = Math.Min(idealWidthFromHeight, maxWidth); 
        computedSize = new Size(
         computedWidth, 
         maxHeight - Math.Abs((b * computedWidth)/d)); 
       } 
      } 
      else if ((0 == a) || (0 == d)) 
      { 
       // Check for 90/270 degree special cases 
       double maxWidth = (infiniteHeight ? double.PositiveInfinity : maxWidthFromHeight); 
       double maxHeight = (infiniteWidth ? double.PositiveInfinity : maxHeightFromWidth); 
       if ((0 == a) && (0 == d)) 
       { 
        // No constraints 
        computedSize = new Size(maxWidth, maxHeight); 
       } 
       else if (0 == a) 
       { 
        // Constrained by width 
        double computedHeight = Math.Min(idealHeightFromHeight, maxHeight); 
        computedSize = new Size(
         maxWidth - Math.Abs((d * computedHeight)/b), 
         computedHeight); 
       } 
       else if (0 == d) 
       { 
        // Constrained by height 
        double computedWidth = Math.Min(idealWidthFromWidth, maxWidth); 
        computedSize = new Size(
         computedWidth, 
         maxHeight - Math.Abs((a * computedWidth)/c)); 
       } 
      } 
      else if (idealHeightFromWidth <= ((slopeFromHeight * idealWidthFromWidth) + maxHeightFromHeight)) 
      { 
       // Check the width midpoint for viability (by being below the height constraint line) 
       computedSize = new Size(idealWidthFromWidth, idealHeightFromWidth); 
      } 
      else if (idealHeightFromHeight <= ((slopeFromWidth * idealWidthFromHeight) + maxHeightFromWidth)) 
      { 
       // Check the height midpoint for viability (by being below the width constraint line) 
       computedSize = new Size(idealWidthFromHeight, idealHeightFromHeight); 
      } 
      else 
      { 
       // Neither midpoint is viable; use the intersection of the two constraint lines instead 
       // Compute width by setting heights equal (m1*x+c1=m2*x+c2) 
       double computedWidth = (maxHeightFromHeight - maxHeightFromWidth)/(slopeFromWidth - slopeFromHeight); 
       // Compute height from width constraint line (y=m*x+c; using height would give same result) 
       computedSize = new Size(
        computedWidth, 
        (slopeFromWidth * computedWidth) + maxHeightFromWidth); 
      } 

      // Return result 
      //DiagnosticWriteLine(" ComputeLargestTransformedSize > " + computedSize); 
      return computedSize; 
     } 

     /// <summary> 
     /// Returns true if Size a is smaller than Size b in either dimension. 
     /// </summary> 
     /// <param name="a">Second Size.</param> 
     /// <param name="b">First Size.</param> 
     /// <returns>True if Size a is smaller than Size b in either dimension.</returns> 
     private static bool IsSizeSmaller(Size a, Size b) 
     { 
      // WPF equivalent of following code: 
      // return ((a.Width < b.Width) || (a.Height < b.Height)); 
      return ((a.Width + AcceptableDelta < b.Width) || (a.Height + AcceptableDelta < b.Height)); 
     } 

     /// <summary> 
     /// Rounds the non-offset elements of a Matrix to avoid issues due to floating point imprecision. 
     /// </summary> 
     /// <param name="matrix">Matrix to round.</param> 
     /// <param name="decimals">Number of decimal places to round to.</param> 
     /// <returns>Rounded Matrix.</returns> 
     private static Matrix RoundMatrix(Matrix matrix, int decimals) 
     { 
      return new Matrix(
       Math.Round(matrix.M11, decimals), 
       Math.Round(matrix.M12, decimals), 
       Math.Round(matrix.M21, decimals), 
       Math.Round(matrix.M22, decimals), 
       matrix.OffsetX, 
       matrix.OffsetY); 
     } 

     /// <summary> 
     /// Implements WPF's Rect.Transform on Silverlight. 
     /// </summary> 
     /// <param name="rect">Rect to transform.</param> 
     /// <param name="matrix">Matrix to transform with.</param> 
     /// <returns>Bounding box of transformed Rect.</returns> 
     private static Rect RectTransform(Rect rect, Matrix matrix) 
     { 
      // WPF equivalent of following code: 
      // Rect rectTransformed = Rect.Transform(rect, matrix); 
      Point leftTop = matrix.Transform(new Point(rect.Left, rect.Top)); 
      Point rightTop = matrix.Transform(new Point(rect.Right, rect.Top)); 
      Point leftBottom = matrix.Transform(new Point(rect.Left, rect.Bottom)); 
      Point rightBottom = matrix.Transform(new Point(rect.Right, rect.Bottom)); 
      double left = Math.Min(Math.Min(leftTop.X, rightTop.X), Math.Min(leftBottom.X, rightBottom.X)); 
      double top = Math.Min(Math.Min(leftTop.Y, rightTop.Y), Math.Min(leftBottom.Y, rightBottom.Y)); 
      double right = Math.Max(Math.Max(leftTop.X, rightTop.X), Math.Max(leftBottom.X, rightBottom.X)); 
      double bottom = Math.Max(Math.Max(leftTop.Y, rightTop.Y), Math.Max(leftBottom.Y, rightBottom.Y)); 
      Rect rectTransformed = new Rect(left, top, right - left, bottom - top); 
      return rectTransformed; 
     } 

     /// <summary> 
     /// Implements WPF's Matrix.Multiply on Silverlight. 
     /// </summary> 
     /// <param name="matrix1">First matrix.</param> 
     /// <param name="matrix2">Second matrix.</param> 
     /// <returns>Multiplication result.</returns> 
     private static Matrix MatrixMultiply(Matrix matrix1, Matrix matrix2) 
     { 
      // WPF equivalent of following code: 
      // return Matrix.Multiply(matrix1, matrix2); 
      return new Matrix(
       (matrix1.M11 * matrix2.M11) + (matrix1.M12 * matrix2.M21), 
       (matrix1.M11 * matrix2.M12) + (matrix1.M12 * matrix2.M22), 
       (matrix1.M21 * matrix2.M11) + (matrix1.M22 * matrix2.M21), 
       (matrix1.M21 * matrix2.M12) + (matrix1.M22 * matrix2.M22), 
       ((matrix1.OffsetX * matrix2.M11) + (matrix1.OffsetY * matrix2.M21)) + matrix2.OffsetX, 
       ((matrix1.OffsetX * matrix2.M12) + (matrix1.OffsetY * matrix2.M22)) + matrix2.OffsetY); 
     } 

     /// <summary> 
     /// Implements WPF's Matrix.HasInverse on Silverlight. 
     /// </summary> 
     /// <param name="matrix">Matrix to check for inverse.</param> 
     /// <returns>True if the Matrix has an inverse.</returns> 
     private static bool MatrixHasInverse(Matrix matrix) 
     { 
      // WPF equivalent of following code: 
      // return matrix.HasInverse; 
      return (0 != ((matrix.M11 * matrix.M22) - (matrix.M12 * matrix.M21))); 
     } 
    } 
} 

在App.xaml文件

添加共同

xmlns:common="using:Common" 

创建ApplicationResources内一个新的样式命名空间

<Application.Resources> 
    <Style TargetType="common:LayoutTransformer"> 
     <Setter Property="Foreground" Value="#FF000000"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="common:LayoutTransformer"> 
        <Grid x:Name="TransformRoot" Background="{TemplateBinding Background}"> 
         <ContentPresenter 
        x:Name="Presenter" 
        Content="{TemplateBinding Content}" 
        ContentTemplate="{TemplateBinding ContentTemplate}"/> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Application.Resources> 

我们通过90度

旋转文本块逆时针

共同

xmlns:common="using:Common" 

,并使用此代码

<common:LayoutTransformer> 
    <common:LayoutTransformer.LayoutTransform> 
    <RotateTransform Angle="-90" /> 
    </common:LayoutTransformer.LayoutTransform> 
    <TextBlock Text="CATEGORIES" 
      FontSize="30"/> 
</common:LayoutTransformer> 
+0

您的OneDrive链接不再可用:( – ManIkWeet

+1

我已更新了答案:)您现在可以使用它 –

+0

我喜欢Stack Overflow上可用的代码,请点赞! :) – ManIkWeet

2

如果您旋转边框(父),则TextBlock也将被旋转,因为它是边框的子项。

<Border Height="80" 
    Background="Teal"> 
     <Border.RenderTransform> 
      <RotateTransform Angle="-90" /> 
     </Border.RenderTransform> 
     <TextBlock Text="CATEGORIES" 
     Foreground="White" 
     FontFamily="Segoe UI Black" 
     FontSize="30"> 
     </TextBlock> 
    </Border> 
+0

的作品,但现在边界元素不适合在屏幕上。根据窗口宽度调整屏幕高度,并且在窗口大小更改时不调整窗口大小。使用[this](http://igrali.com/2012/09/17/layout-transform-in-windows-8-winrt-xaml/)对我来说工作得很好。 –

+0

您可以像“那样定义边框的大小,这是可以接受的吗? – kennyzx

+0

如果缩小窗口大小,则显式设置宽度和高度会截断边框内的文本。 –