2012-09-25 132 views
0

我在WPF中創建了一個groupbox以包含我的控件,並且想知道是否可以將標題更改爲垂直運行而不是水平運行?這是我的代碼;更改Groupbox標題方向

<GroupBox Grid.Column="0"> 
    <GroupBox.Header> 
     Navigation 
    </GroupBox.Header> 
    <StackPanel Orientation="Vertical" > 
     <Button>Up</Button> 
     <Button>Down</Button> 
    </StackPanel> 
</GroupBox> 

我已經探索了性能,但似乎無法找到比改變包含在GroupBox.Header元素中的一個TextBlock的任何其他。

<GroupBox Grid.Column="0"> 
    <GroupBox.Header> 
     <Orientation> 
      <!-- Invalid --> 
     </Orientation> 
    </GroupBox.Header> 
    <StackPanel Orientation="Vertical" > 
     <Button>Up</Button> 
     <Button>Down</Button> 
    </StackPanel> 
</GroupBox> 

回答

1

你可以,但它是不漂亮! Badly rotated header

<GroupBox> 
    <GroupBox.Header> 
     <TextBlock Text="Hello"> 
      <TextBlock.RenderTransform> 
       <RotateTransform Angle="90" CenterX="0" CenterY="0" /> 
      </TextBlock.RenderTransform> 
     </TextBlock> 
    </GroupBox.Header> 
    <TextBlock Text="World!"/> 
</GroupBox> 

你也將需要修改style of the GroupBox支持這一點。

這看起來像它只是一個有幾行,兩個內容主持人和幾個邊界的網格,所以應該可以將其轉換爲列並從那裏出發。我實際上是將Rotate放在ContentPresenter的頭部,這樣你就可以將你的風格應用到任何你想要的地方。

最後更新

通過提取模板出來的標準控制,我們可以修改它以輪動頭的,但是我們也發現,有用來掩蓋周圍邊框的轉換器。通過使用反編譯器(DotPeek),我們還可以切換行和列來將間隙移動到一側。

Rotated GroupBox

所以模板看起來像這樣

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 

    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <BorderGapMaskConverter x:Key="BorderGapMaskConverter"/> 
    <Style x:Key="GroupBoxStyle1" TargetType="{x:Type GroupBox}"> 
     <Setter Property="BorderBrush" Value="#D5DFE5"/> 
     <Setter Property="BorderThickness" Value="1"/> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type GroupBox}"> 
        <Grid SnapsToDevicePixels="true"> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="Auto"/> 
          <ColumnDefinition Width="Auto"/> 
          <ColumnDefinition Width="*"/> 
          <ColumnDefinition Width="6"/> 
         </Grid.ColumnDefinitions> 
         <Grid.RowDefinitions> 
          <RowDefinition Height="6"/> 
          <RowDefinition Height="Auto"/> 
          <RowDefinition Height="*"/> 
          <RowDefinition Height="6"/> 
         </Grid.RowDefinitions> 
         <Border BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="3" Grid.Column="1" CornerRadius="4" Grid.Row="0" Grid.RowSpan="4"/> 
         <Border x:Name="Header" Grid.Column="0" Padding="3,1,3,0" Grid.Row="1" Grid.ColumnSpan="2"> 
          <Border.LayoutTransform> 
           <RotateTransform Angle="-90"/> 
          </Border.LayoutTransform> 
          <ContentPresenter ContentSource="Header" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
         </Border> 
         <ContentPresenter Grid.RowSpan="2" Grid.Row="1" Margin="{TemplateBinding Padding}" Grid.Column="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
         <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" Grid.RowSpan="4" CornerRadius="4" Grid.Column="1" Grid.ColumnSpan="3"> 
          <Border.OpacityMask> 
           <MultiBinding ConverterParameter="7" Converter="{StaticResource BorderGapMaskConverter}"> 
            <Binding ElementName="Header" Path="ActualWidth"/> 
            <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/> 
            <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/> 
           </MultiBinding> 
          </Border.OpacityMask> 
          <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3"> 
           <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/> 
          </Border> 
         </Border> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 


<GroupBox Header="Hello world!" Margin="12" Style="{DynamicResource GroupBoxStyle1}"/> 
</Window> 

而且修改後的轉換器看起來像這樣

// Type: System.Windows.Controls.BorderGapMaskConverter 
// Assembly: PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 
// Assembly location: C:\Windows\Microsoft.NET\assembly\GAC_MSIL\PresentationFramework\v4.0_4.0.0.0__31bf3856ad364e35\PresentationFramework.dll 

using System; 
using System.Globalization; 
using System.Runtime; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Media; 
using System.Windows.Shapes; 

namespace WfpApplication1 //System.Windows.Controls 
{ 
    public class LeftBorderGapMaskConverter : IMultiValueConverter 
{ 
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 
    public LeftBorderGapMaskConverter() 
    { 
     //  base.ctor(); 
    } 

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     Type type1 = typeof(double); 
     if (parameter == null 
      || values == null 
      || (values.Length != 3 || values[0] == null) 
      || (values[1] == null 
       || values[2] == null 
       || (!type1.IsAssignableFrom(values[0].GetType()) 
        || !type1.IsAssignableFrom(values[1].GetType()))) 
      || !type1.IsAssignableFrom(values[2].GetType())) 
      return DependencyProperty.UnsetValue; 

     Type type2 = parameter.GetType(); 
     if (!type1.IsAssignableFrom(type2) 
      && !typeof(string).IsAssignableFrom(type2)) 
      return DependencyProperty.UnsetValue; 

     double pixels1 = (double)values[0]; 
     double num1 = (double)values[1]; 
     double num2 = (double)values[2]; 
     if (num1 == 0.0 || num2 == 0.0) 
      return (object)null; 

     double pixels2 = !(parameter is string) 
      ? (double)parameter 
      : double.Parse((string)parameter, (IFormatProvider)NumberFormatInfo.InvariantInfo); 

     Grid grid = new Grid(); 
     grid.Width = num1; 
     grid.Height = num2; 
     RowDefinition RowDefinition1 = new RowDefinition(); 
     RowDefinition RowDefinition2 = new RowDefinition(); 
     RowDefinition RowDefinition3 = new RowDefinition(); 
     RowDefinition1.Height = new GridLength(pixels2); 
     RowDefinition2.Height = new GridLength(pixels1); 
     RowDefinition3.Height = new GridLength(1.0, GridUnitType.Star); 
     grid.RowDefinitions.Add(RowDefinition1); 
     grid.RowDefinitions.Add(RowDefinition2); 
     grid.RowDefinitions.Add(RowDefinition3); 
     ColumnDefinition ColumnDefinition1 = new ColumnDefinition(); 
     ColumnDefinition ColumnDefinition2 = new ColumnDefinition(); 
     ColumnDefinition1.Width = new GridLength(num2/2.0); 
     ColumnDefinition2.Width = new GridLength(1.0, GridUnitType.Star); 
     grid.ColumnDefinitions.Add(ColumnDefinition1); 
     grid.ColumnDefinitions.Add(ColumnDefinition2); 
     Rectangle rectangle1 = new Rectangle(); 
     Rectangle rectangle2 = new Rectangle(); 
     Rectangle rectangle3 = new Rectangle(); 
     rectangle1.Fill = (Brush)Brushes.Black; 
     rectangle2.Fill = (Brush)Brushes.Black; 
     rectangle3.Fill = (Brush)Brushes.Black; 

     Grid.SetColumnSpan((UIElement)rectangle1, 2); 
     Grid.SetColumn((UIElement)rectangle1, 0); 
     Grid.SetRow((UIElement)rectangle1, 0); 
     Grid.SetColumn((UIElement)rectangle2, 1); 
     Grid.SetRow((UIElement)rectangle2, 1); 
     Grid.SetColumnSpan((UIElement)rectangle3, 2); 
     Grid.SetColumn((UIElement)rectangle3, 0); 
     Grid.SetRow((UIElement)rectangle3, 2); 
     grid.Children.Add((UIElement)rectangle1); 
     grid.Children.Add((UIElement)rectangle2); 
     grid.Children.Add((UIElement)rectangle3); 
     return (object)new VisualBrush((Visual)grid); 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     return new object[1] 
      { 
      Binding.DoNothing 
      }; 
    } 
} 
} 
+0

感謝您的代碼,是的,我會努力減少白色空間,否則它看起來不正確。 – wonea

+1

只需刪除中的所有內容即可完全刪除白色間隙。 – AlSki

+0

謝謝我需要弄清楚如何繪製文本上方的文本,即改變繪圖順序。 – wonea

1

我不認爲你可以通過簡單地改變屬性或使用頭模板來獲得組框頭。相反,您可以嘗試RotateTransform,但它也會旋轉組框內的所有元素。所以你必須分別對組合框內的容器元素進行反轉換。

<GroupBox Header="Navigation" Grid.Column="0"> 
    <GroupBox.RenderTransform> 
     <RotateTransform Angle="-90" CenterX="100" CenterY="100" /> 
    </GroupBox.RenderTransform> 
    <StackPanel Orientation="Vertical"> 
     <StackPanel.RenderTransform> 
      <RotateTransform Angle="90" CenterX="100" CenterY="100" /> 
     </StackPanel.RenderTransform> 
     <Button>Up</Button> 
     <Button>Down</Button> 
    </StackPanel> 
</GroupBox> 

獲取元素對齊會是麻煩的,你更是預示了與整天CenterXCenterY性能發揮。但是,如果這是你想要什麼,我想這是得到它:)

+0

很好的答案,我可以放置在這裏面一個旋轉StackPanel中,和會做這項工作。如您所說,儘管動態調整GroupBox的大小可能會非常棘手。 – wonea

+0

你能改變一個元素被塗上的點/角嗎?所以你不必改變CenterX或CenterY? – wonea

1

我能想象垂直頭座的兩個選項中組框的方式:

1)旋轉的文本塊,但不要」的「流」牛逼旋轉字母

2)旋轉文本塊本身

下面是XAML這兩個選項:

<Grid> 
     <Grid.Resources> 
      <System:String x:Key="header">Vertical</System:String> 
     </Grid.Resources> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <GroupBox Grid.Row="0"> 
      <GroupBox.HeaderTemplate> 
       <DataTemplate> 
        <ItemsControl ItemsSource="{StaticResource header}" /> 
       </DataTemplate> 
      </GroupBox.HeaderTemplate> 
     </GroupBox> 
     <GroupBox Grid.Row="1"> 
      <GroupBox.HeaderTemplate> 
       <DataTemplate> 
        <TextBlock Text="{StaticResource header}"> 
         <TextBlock.LayoutTransform> 
          <RotateTransform Angle="90" /> 
         </TextBlock.LayoutTransform> 
        </TextBlock> 
       </DataTemplate> 
      </GroupBox.HeaderTemplate> 
     </GroupBox> 
    </Grid> 
+0

謝謝,我喜歡第一個GroupBox的垂直刻字。 – wonea