开发者

WPF GroupBox with no header space

Easy one, I would like to have a GroupBox 开发者_如何学运维with no header space

The closest thing is a border, but the border "by default" does not have the same Style as the group box.

What's the easiest way (least xaml / code) to get the desired GroupBox ?

Thanks


If you really don't want a border, then there can be these 2 solutions:


(1) Edit template in blend :

  • Right click on GroupBox > Edit Template > Edit Copy > OK
  • Search for section

      <Border.OpacityMask>
           <MultiBinding Converter="{StaticResource BorderGapMaskConverter}" ConverterParameter="7">
                ......
           </MultiBinding>
      </Border.OpacityMask>
    
  • Delete this (above mentioned) section.. You have just removed the "gap"

  • Now this will work if you do not set the header (as you have shown in example). However if you set the header, it'll go behind the border. So to correct this, just set Panel.ZIndex="-1" in the border that was enclosing the section you just deleted (it looks like <Border BorderBrush="White" BorderThickness= ...)

(2) Use duplicate GroupBox and flip it horizontally and place it beneath original groupbox:

  • Put this code below your groupbox (assuming your groupbox's name is 'OriginalGroupbox')

     <GroupBox Header="" Focusable="False" Panel.ZIndex="-1" 
               Width="{Binding ActualWidth, ElementName=OriginalGroupbox}" 
               Height="{Binding ActualHeight, ElementName=OriginalGroupbox}" 
               IsEnabled="{Binding IsEnabled, ElementName=OriginalGroupbox}"
               RenderTransformOrigin="0.5,0.5">
               <GroupBox.RenderTransform>
                    <ScaleTransform ScaleX="-1"/>
               </GroupBox.RenderTransform>
     </GroupBox>
    
  • Enclose both these GroupBox in a Grid like this:

    <Grid>
         <GroupBox x:Name="OriginalGroupbox" Header="Mihir" ...>
            ...
         </GroupBox>
         <GroupBox Header="" Width="{Binding ActualWidth, ElementName=OriginalGroupbox}" ...>
            ...
         </GroupBox>
    </Grid>
    


You can emulate the style of the group box by changing your border to have rounded corners and a different color. Here is a border that looks pretty close to the GroupBox border:

<Border BorderThickness="1" CornerRadius="4" Height="100" Width="100" Padding="5" BorderBrush="LightGray"><TextBlock>Border</TextBlock></Border>

alt text http://img264.imageshack.us/img264/6748/borderm.png


Building on Mihir Gokani's answer, you can change the default template to use a Trigger to change the header's padding to nothing, when the header is null or empty.

Use the following style on the GroupBox, should fix it.

<BorderGapMaskConverter x:Key="BorderGapMaskConverter"/>
<Style x:Key="GroupBoxStyle" 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="6"/>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="6"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="6"/>
                    </Grid.RowDefinitions>
                    <Border BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="4" Grid.Column="0" CornerRadius="4" Grid.Row="1" Grid.RowSpan="3"/>
                    <Border x:Name="Header" Grid.Column="1" Padding="3,1,3,0" Grid.Row="0" Grid.RowSpan="2">
                        <ContentPresenter ContentSource="Header" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <ContentPresenter Grid.ColumnSpan="2" Grid.Column="1" Margin="{TemplateBinding Padding}" Grid.Row="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" Grid.ColumnSpan="4" CornerRadius="4" Grid.Row="1" Grid.RowSpan="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.Triggers>
                    <Trigger Property="Header" Value="{x:Null}">
                        <Setter TargetName="Header" Property="Padding" Value="0" />                                 
                    </Trigger>
                        <Trigger Property="Header" Value="">
                            <Setter TargetName="Header" Property="Padding" Value="0" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Note the only addition is:

<ControlTemplate.Triggers>
    <Trigger Property="Header" Value="{x:Null}">
        <Setter TargetName="Header" Property="Padding" Value="0" />                                 
    </Trigger>
    <Trigger Property="Header" Value="">
        <Setter TargetName="Header" Property="Padding" Value="0" />
    </Trigger>
</ControlTemplate.Triggers>


the whole code and demo of its use

<UserControl.Resources>
    <ResourceDictionary>
        <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="6"/>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="6"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="6"/>
                        </Grid.RowDefinitions>
                        <Border BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.ColumnSpan="4" Grid.Column="0" CornerRadius="4" Grid.Row="1" Grid.RowSpan="3"/>
                        <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" Grid.ColumnSpan="4" CornerRadius="4" Grid.Row="1" Grid.RowSpan="3">

                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3">
                                <Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/>
                            </Border>
                        </Border>
                        <Border x:Name="Header" Grid.Column="1" Padding="3,1,3,0" Grid.Row="0" Grid.RowSpan="2">
                            <ContentPresenter ContentSource="Header" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                        <ContentPresenter Grid.ColumnSpan="2" Grid.Column="1" Margin="{TemplateBinding Padding}" Grid.Row="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
        </ResourceDictionary>
</UserControl.Resources>

<Grid>

    <GroupBox Header="" HorizontalAlignment="Left" Margin="70,39,0,0" VerticalAlignment="Top" Height="169.96" Width="299.697" Style="{DynamicResource GroupBoxStyle1}"/>
</Grid>


I was looking for a similar solution. I needed a group box style where the border was closed only when there is no header text.

I'm not convinced it's the nicest solution, but it works fine...

We have a converter (works with text only atm):

public class GroupBoxHeaderVisibilityConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        ContentPresenter header = values[0] as ContentPresenter;
        if (header != null)
        {
            string text = header.Content as string;
            if (string.IsNullOrEmpty(text))
            {
                return 0.0;
            }
        }
        return values[1];
    }

    public object[] ConvertBack(object value, System.Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }

    #endregion
}

and the modifications to the groupbox style:

<Border
    x:Name="Header"
    Grid.Column="1"
    Grid.Row="0"
    Grid.RowSpan="2"
    Padding="3,1,3,0">
    <Border.Tag>
        <MultiBinding Converter="{StaticResource GroupBoxHeaderVisibilityConverter}">
            <Binding Path="Content" ElementName="groupBoxLabel" />
            <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
        </MultiBinding> 
    </Border.Tag>
    <Label x:Name="groupBoxLabel"
        FontSize="{StaticResource Fonts_SmallFontSize}"
        Foreground="{TemplateBinding Foreground}">
        <ContentPresenter
            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
            ContentSource="Header"
            RecognizesAccessKey="True" />
    </Label>
</Border>
<ContentPresenter
    Margin="{TemplateBinding Padding}"
    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
    Grid.Column="1"
    Grid.ColumnSpan="2"
    Grid.Row="2" />
<Border
    Grid.ColumnSpan="4"
    Grid.Row="1"
    Grid.RowSpan="3"
    BorderBrush="Transparent"
    BorderThickness="{TemplateBinding BorderThickness}"
    CornerRadius="4">
    <Border.OpacityMask>                                
        <MultiBinding
            Converter="{StaticResource BorderGapMaskConverter}"
            ConverterParameter="7">
            <Binding ElementName="Header" Path="Tag" />
            <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>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜