2012-09-25 2 views
0

Я создаю групповой ящик в WPF, чтобы содержать мои элементы управления, и задавался вопросом, можно ли изменить заголовок, чтобы работать вертикально, а не горизонтально? Вот мой код;Изменение ориентации заголовка Groupbox

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

Я исследовал свойства, но не могу найти ничего, кроме изменения в TextBlock, содержащийся в элементе GroupBox.Header.

<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, который делает заголовок, поэтому вы можете просто применить свой стиль, где бы вы этого ни хотели.

Final Update

Извлекая шаблон из стандартного контроля мы можем изменить его, чтобы переместить заголовок раунд, однако мы также считаем, что есть конвертер используется для маскировки границы вокруг. Используя декомпилятор (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> 

Получение элементов для выравнивания будет неаккуратно и вы Виль должны играть с CenterX и CenterY свойства в течение всего дня. Но если это то, что вы хотите, я думаю, это способ получить его :)

+0

Очень хороший ответ, я мог бы поместить повернутый StackPanel внутри этого, и что будет выполнять эту работу. Хотя создание динамического размера GroupBox может быть сложным, как вы говорите. – wonea

+0

Можете ли вы изменить точку/угол, на котором нарисован элемент?Так что вам не нужно менять CenterX или CenterY? – wonea

1

Я могу представить себе два варианта вертикального заголовка в поле группы:

1) Поверните «поток» в TextBlock, но Дон» т повернуть буквы

2) Поворот TextBlock сама

Вот эти два варианта в 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