1

しばらく取り組んできたWPFの問題について助けを求めています。タブビューのスタイルを設定し、タブを左に移動して垂直に表示しました。これらのタブは、左上と左下に丸い角がある境界線の内側にあります。

通常のタブhttp://gallery.me.com/theplatz/100006/TabGood.png?derivative=medium&source=web.png&type=medium&ver=12464623560001

タブをスクロールすると問題が発生します。ここに示すように、丸みを帯びた角がスクロールされたコンテンツをクリップする代わりに、コンテンツは実際には角の上に乗っています。

重複するタブhttp://gallery.me.com/theplatz/100006/TabBad/web.png?ver=12464623500001

XAMLは次のとおりです。

<Style x:Key="SidebarTabControl" TargetType="TabControl">
    <Setter Property="Background" Value="#FFC6D3DE" />
    <Setter Property="Padding" Value="0,20,0,0" />
    <Setter Property="TabStripPlacement" Value="Left" />
    <Setter Property="IsSynchronizedWithCurrentItem" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabControl}">
                <Grid KeyboardNavigation.TabNavigation="Local">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200" MinWidth="150" MaxWidth="400" />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>

                <Border
                    CornerRadius="10,0,0,10"
                    Background="{TemplateBinding Background}">
                    <ScrollViewer Grid.Column="0"
                        VerticalScrollBarVisibility="Auto"
                        HorizontalScrollBarVisibility="Disabled"
                        ClipToBounds="True">
                        <Border Padding="{TemplateBinding Padding}">        
                        <TabPanel
                            IsItemsHost="True"
                            KeyboardNavigation.TabIndex="1"
                            Background="Transparent">
                        </TabPanel>
                        </Border>
                    </ScrollViewer>
                </Border>

                <ContentPresenter
                    Grid.Column="1"
                    Margin="0"
                    ContentSource="SelectedContent" />

                <GridSplitter Grid.Column="0"
                  HorizontalAlignment="Right"
                  VerticalAlignment="Stretch"
                  Background="{StaticResource SplitterBrush}" 
                  ShowsPreview="True"
                  Width="1" />
              </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="SidebarTab" TargetType="TabItem">
    <Setter Property="Padding" Value="10,12,2,12" />
    <Setter Property="BorderThickness" Value="0,1,0,1" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <Border Padding="{TemplateBinding Padding}" 
                    Name="tab" 
                    BorderThickness="{TemplateBinding BorderThickness}" 
                    BorderBrush="{StaticResource SidebarTabBorderBrush}">
                    <ContentPresenter Style="{StaticResource SidebarTabForegroundStyle}" Name="content" ContentSource="Header" />
                </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrushSelected}" />
                        <Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrushSelected}" />
                        <Setter TargetName="content" Property="Style" Value="{StaticResource SidebarTabForegroundStyleSelected}" />
                    </Trigger>
                    <Trigger Property="IsSelected" Value="False">
                        <Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrush}" />
                        <Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrush}" />
                        <Setter TargetName="content" Property="Style" Value="{StaticResource SidebarTabForegroundStyle}" />
                    </Trigger>
                </ControlTemplate.Triggers>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

私が探していることを達成する方法について何かアイデアはありますか?ZIndexのトリックをいくつか試しましたが、うまくいかなかったようです。

4

3 に答える 3

3

Clip境界線の輪郭に一致するジオメトリを使用して、丸みを帯びた境界線にを設定できます。

<Border>
    <Border.Clip>
        <RectangleGeometry Rect="..." RadiusX="..." RadiusY="..."/>
    </Border.Clip>
</Border>

おそらくお気づきかもしれませんがClipToBoundsBorderコーナーと丸みを帯びたエッジの間の領域が境界にあるBorderため、は機能しないことに注意してください。クリップされません。

于 2009-07-01T15:51:20.967 に答える
3

私が探していたものを達成するために、私はここにある解決策を使用し、私のニーズに合うようにそれを修正しました。これが私が最終的に得たものです:

<Style x:Key="SidebarTabControl" TargetType="TabControl">
    <Setter Property="Background" Value="#FFC6D3DE" />
    <Setter Property="Padding" Value="0,20,0,20" />
    <Setter Property="TabStripPlacement" Value="Left" />
    <Setter Property="IsSynchronizedWithCurrentItem" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabControl}">
                <Grid KeyboardNavigation.TabNavigation="Local">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="200" MinWidth="150" MaxWidth="400" />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>

            <!-- Background of the sidebar and our clipping bounds -->
            <Border Grid.Column="0"
                CornerRadius="10,0,0,10"
                    Background="{TemplateBinding Background}"
                Name="mask" />

            <!-- Border necessary so that the top tab does not get clipped prematurely -->
            <Border Grid.Column="0" Background="Transparent">
                <!-- Add opacity mask to clip contents as they're scrolled -->
                <Border.OpacityMask>
                        <VisualBrush Visual="{Binding ElementName=mask}"/>
                </Border.OpacityMask>
                <ScrollViewer
                VerticalScrollBarVisibility="Visible"
                HorizontalScrollBarVisibility="Disabled">
                <Border Padding="{TemplateBinding Padding}">        
                        <TabPanel
                        IsItemsHost="True"
                        KeyboardNavigation.TabIndex="1"
                        Background="Transparent">
                    </TabPanel>
                </Border>
                 </ScrollViewer>
            </Border>

            <ContentPresenter
                Grid.Column="1"
                        Margin="0"
                        ContentSource="SelectedContent" />

            <GridSplitter Grid.Column="0"
                        HorizontalAlignment="Right"
                        VerticalAlignment="Stretch"
                        Background="{StaticResource SplitterBrush}" 
                        ShowsPreview="True"
                        Width="1" />
              </Grid>
        </ControlTemplate>
    </Setter.Value>
   </Setter>
</Style>

編集:最初のTabItemでクリッピングの問題の解決策を見つけました。ScrollViewを2番目の境界線の内側にネストし、この境界線にOpacityMaskを適用すると、ScrollViewではなく問題が修正されました。さらに、クリップが時期尚早に発生しないように、OpacityMaskが適用されていた境界線にBackground="Transparent"を明示的に設定する必要がありました。

于 2009-07-01T17:29:41.143 に答える
0

私も同様の問題を抱えていましたが、境界線がコンテンツを自然にクリップすると想定していました。とにかくコンテンツが突き抜けるだけの場合は、コーナー半径を実装するのは何が良いことでしょう。

ボーダーを継承するカスタムコントロールを作成し、その中にボーダーのクリップを設定することになりました。簡単に言うと、ArrangeOverrideをオーバーライドして境界線の最終サイズを取得し、クリップとして使用するRectangleGeometryを作成しました。

public class NodeBorder : Border
{
    static NodeBorder()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NodeBorder), new FrameworkPropertyMetadata(typeof(NodeBorder)));
    }


    protected override Size ArrangeOverride(Size finalSize)
    {
        Rect rect= new Rect(0, 0,finalSize.Width,finalSize.Height);
        RectangleGeometry geometry = new RectangleGeometry(rect,this.CornerRadius.TopLeft,this.CornerRadius.TopRight);
        this.Clip = geometry;

        return base.ArrangeOverride(finalSize);
    }
}

VSでカスタムコントロールを作成すると、Generic.xamlにコントロールのスタイルが作成されます。スタイルを削除するだけで、必要ありません。

次に、xamlで、Borderの代わりにyournamespace:NodeBorderを使用できます。

ボーダーの良さはすべて得られますが、クリッピングが組み込まれています。余分なマークアップはなく、ボーダーのレイアウトにぴったりのサイズになります。

編集:境界線の内側のクリッピングが役立つかもしれないことに気づきました。

上記を変更して、依存関係プロパティContentClip...を含めることができます。

        public static readonly DependencyProperty ContentClipProperty =
        DependencyProperty.Register("ContentClip", typeof(Geometry), typeof(NodeBorder), new PropertyMetadata(null));

    protected override Size ArrangeOverride(Size finalSize)
    {
        Rect rect= new Rect(0, 0,finalSize.Width-(this.BorderThickness.Left+ this.BorderThickness.Right),finalSize.Height-(this.BorderThickness.Top+ this.BorderThickness.Bottom));
        RectangleGeometry geometry = new RectangleGeometry(rect,this.CornerRadius.TopLeft-1,this.CornerRadius.TopRight-1);
        this.ContentClip = geometry;

        return base.ArrangeOverride(finalSize);
    }

...そしてそのように使用されます:

                <Controls:NodeBorder
                    x:Name="xxx"
                    Canvas.Top="300"
                    Canvas.Left="10"
                    CornerRadius="20"
                    BorderBrush="Red"
                    BorderThickness="2"
                    Panel.ZIndex="10"
                    >
                    <Rectangle Width="60" Height="60"
                               Fill="Blue"
                               Clip="{Binding ElementName=xxx, Path=ContentClip}"
                        />
                </Controls:NodeBorder>

于 2021-10-01T14:43:10.220 に答える