XAML 路径大小和定位

发布于 2024-09-16 13:13:19 字数 1309 浏览 7 评论 0原文

我正在尝试使用路径和矩形为 TabItem 设计一个模板。选项卡布局的侧面是容纳设计中曲线的路径。我在让侧面正确对齐/调整大小时遇到​​问题。这是我的 XAML:(

<StackPanel Orientation="Horizontal">
 <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 97.1985,101.669L 104.824,95.0005C 105.574,94.3338 106.921,93.8627 107.824,93.9171L 107.824,101.667L 97.1985,101.669 Z "/>
 <Grid>
          <Rectangle Grid.Column="1" Fill="#FF000000"/>
  <ContentControl Grid.Column="1" x:Name="HeaderTopSelected" FontSize="{TemplateBinding FontSize}" Foreground="{TemplateBinding Foreground}" IsTabStop="False" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
 </Grid>
 <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 118.714,101.678L 111.088,95.0097C 110.338,94.343 108.991,93.8719 108.088,93.9264L 108.088,101.676L 118.714,101.678 Z "/>
</StackPanel>

对于缺少换行符,我深表歉意。我是 StackOverflow 的新手,不知道如何插入它们,也没有时间弄清楚它:D)

发布的代码片段 几乎有效:侧面路径的大小正确,但它们不显示在一行中,它们重叠在矩形/下一个元素后面。如果我设置固定宽度,它们也可以工作,但我不能将宽度设置为固定,它们需要保持流畅,以防选项卡的内容超过基本高度。

这是我想要得到的想法
边(路径)根据 ContentControl 的高度均匀增长

I am trying to design a template for a TabItem using paths and rectangles. The sides of the tab layout are paths to accommodate curves in the design. I am having a problem with getting the sides to line up/resize correctly. Here's my XAML:

<StackPanel Orientation="Horizontal">
 <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 97.1985,101.669L 104.824,95.0005C 105.574,94.3338 106.921,93.8627 107.824,93.9171L 107.824,101.667L 97.1985,101.669 Z "/>
 <Grid>
          <Rectangle Grid.Column="1" Fill="#FF000000"/>
  <ContentControl Grid.Column="1" x:Name="HeaderTopSelected" FontSize="{TemplateBinding FontSize}" Foreground="{TemplateBinding Foreground}" IsTabStop="False" Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
 </Grid>
 <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 118.714,101.678L 111.088,95.0097C 110.338,94.343 108.991,93.8719 108.088,93.9264L 108.088,101.676L 118.714,101.678 Z "/>
</StackPanel>

(I apologize for the lack of line breaks. I'm new to StackOverflow and don't know how to insert them, nor do I have the time to figure it out :D)

The code snippet posted almost works: The side paths are the correct size, but they do not display in a line, they overlap behind the rectangle/next element. If I set a fixed width they work as well, but I can't set the width as fixed, they need to be fluid in case the content of the tab exceeds the basic height.

This is an idea of what I would like to get

The sides (paths) grow uniformally based on the height of the ContentControl

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

︶葆Ⅱㄣ 2024-09-23 13:13:29

采取 3(现在我们知道要求是什么):

基本上,为了获得所需的效果,您需要 2 个侧面部分在高度发生变化时调整其宽度,以保持固定的纵横比。这将迫使父容器随着实际内容变高并且侧面变高以匹配而扩展。没有一个容器(包括 ViewBox)完全按照这种方式工作。

您可以使用自定义容器来执行此操作,但首选解决方案是创建一个在高度更改时保留其对象的纵横比的行为。我们将其称为固定方面行为:

using System.Windows;
using System.Windows.Interactivity;

namespace SilverlightApplication1
{
    public class FixedAspectRatioBehavior : TargetedTriggerAction<FrameworkElement>
    {
        public double AspectRatio { get; set; }

        protected override void OnAttached()
        {
            base.OnAttached();
            FrameworkElement element = this.AssociatedObject as FrameworkElement;
            if (element != null)
            {
                AspectRatio = element.Width/element.Height;
                element.SizeChanged += new SizeChangedEventHandler(element_SizeChanged);
            }
        }

        void element_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            FrameworkElement element = AssociatedObject as FrameworkElement;
            element.Width = element.Height * AspectRatio;
        }

        protected override void Invoke(object parameter)
        {
        }
    }
}

布局需要一些工作,因为自动调整大小的元素(路径类型)会根据其父容器执行一些非常奇怪的事情。我必须使用 ViewBoxes 作为路径的父级,并结合行为来获得所需的结果:

alt text

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
    <Viewbox>
            <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 97.1985,101.669L 104.824,95.0005C 105.574,94.3338 106.921,93.8627 107.824,93.9171L 107.824,101.667L 97.1985,101.669 Z " UseLayoutRounding="False" HorizontalAlignment="Left">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseLeftButtonDown">
                        <local:FixedAspectRatioBehavior/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Path>
        </Viewbox>
    <Grid Width="Auto" Background="#FFFF0D0D" Grid.ColumnSpan="1" Grid.Column="1">
        <Rectangle Grid.Column="1" Fill="#FFD21F1F"/>
        <ContentControl Grid.Column="1" x:Name="HeaderTopSelected" FontSize="{TemplateBinding Control.FontSize}" Foreground="{TemplateBinding Control.Foreground}" IsTabStop="False" Cursor="{TemplateBinding FrameworkElement.Cursor}" HorizontalAlignment="{TemplateBinding FrameworkElement.HorizontalAlignment}" VerticalAlignment="{TemplateBinding FrameworkElement.VerticalAlignment}"/>
        <TextBlock TextWrapping="Wrap" FontSize="16"><Run Text="This is just a very string to see "/><LineBreak/><Run Text="what happens  when we get to a size where the container should get larger than the default size"/></TextBlock>
    </Grid>
    <Viewbox Grid.Column="2">
        <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 118.714,101.678L 111.088,95.0097C 110.338,94.343 108.991,93.8719 108.088,93.9264L 108.088,101.676L 118.714,101.678 Z " UseLayoutRounding="False" d:LayoutOverrides="VerticalAlignment">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseLeftButtonDown">
                    <local:FixedAspectRatioBehavior/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Path>
    </Viewbox>
        </Grid>

Take 1 (现在已过时,如下面的 2):

路径的宽度不会沿着堆栈面板中的项目推动。在这方面,除了缩放项目之外,它的宽度是无用的。

为了获得您想要的效果,请将每个路径分组到一个网格中。然后尺寸问题就消失了。

alt text

抱歉将您的矩形变成可怕的红色以清晰显示:)

alt text

下面的 XAML:

<StackPanel Orientation="Horizontal" Width="Auto">
    <Grid>
        <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 97.1985,101.669L 104.824,95.0005C 105.574,94.3338 106.921,93.8627 107.824,93.9171L 107.824,101.667L 97.1985,101.669 Z " UseLayoutRounding="False" d:LayoutOverrides="Width"/>
    </Grid>
    <Grid Width="100" Background="#FFFF0D0D">
        <Rectangle Grid.Column="1" Fill="#FFD21F1F"/>
        <ContentControl Grid.Column="1" x:Name="HeaderTopSelected" FontSize="{TemplateBinding Control.FontSize}" Foreground="{TemplateBinding Control.Foreground}" IsTabStop="False" Cursor="{TemplateBinding FrameworkElement.Cursor}" HorizontalAlignment="{TemplateBinding FrameworkElement.HorizontalAlignment}" VerticalAlignment="{TemplateBinding FrameworkElement.VerticalAlignment}"/>
    </Grid>
    <Grid>
        <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 118.714,101.678L 111.088,95.0097C 110.338,94.343 108.991,93.8719 108.088,93.9264L 108.088,101.676L 118.714,101.678 Z " UseLayoutRounding="False" d:LayoutOverrides="Width"/>
    </Grid>
</StackPanel>

采取 2(现在也已过时,请参阅顶部的采取 3):

如果需要固定的末端宽度,请使用网格而不是堆栈面板(下面的 XAML)。

alt text

如果您需要其他内容,请提供一些所需效果的屏幕截图。

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
    <Path Stretch="Fill" Fill="#FF000000" Data="F1 M 97.1985,101.669L 104.824,95.0005C 105.574,94.3338 106.921,93.8627 107.824,93.9171L 107.824,101.667L 97.1985,101.669 Z " UseLayoutRounding="False" d:LayoutOverrides="Width"/>
    <Grid Width="Auto" Background="#FFFF0D0D" Grid.ColumnSpan="1" Grid.Column="1">
        <Rectangle Grid.Column="1" Fill="#FFD21F1F"/>
        <ContentControl Grid.Column="1" x:Name="HeaderTopSelected" FontSize="{TemplateBinding Control.FontSize}" Foreground="{TemplateBinding Control.Foreground}" IsTabStop="False" Cursor="{TemplateBinding FrameworkElement.Cursor}" HorizontalAlignment="{TemplateBinding FrameworkElement.HorizontalAlignment}" VerticalAlignment="{TemplateBinding FrameworkElement.VerticalAlignment}" Content="Hello there.... this is a long string to see what happens"/>
    </Grid>
    <Path Stretch="Fill" Fill="#FF000000" Data="F1 M 118.714,101.678L 111.088,95.0097C 110.338,94.343 108.991,93.8719 108.088,93.9264L 108.088,101.676L 118.714,101.678 Z " UseLayoutRounding="False" d:LayoutOverrides="Width" Grid.Column="2"/>
        </Grid>

Take 3 (now we know what the requirement is):

Basically to get the desired effect you need your 2 side parts to resize their width if their height changes, in order to keep a fixed aspect ratio. This will force the parent container to expand as the actual content gets taller and the sides get taller to match. none of the containers (including ViewBox) work exactly this way.

You could use a custom container to do this, but the preferred solution would be to create a behaviour that retains its object's aspect ratio on height changes. We will call it a FixedAspectBehavior:

using System.Windows;
using System.Windows.Interactivity;

namespace SilverlightApplication1
{
    public class FixedAspectRatioBehavior : TargetedTriggerAction<FrameworkElement>
    {
        public double AspectRatio { get; set; }

        protected override void OnAttached()
        {
            base.OnAttached();
            FrameworkElement element = this.AssociatedObject as FrameworkElement;
            if (element != null)
            {
                AspectRatio = element.Width/element.Height;
                element.SizeChanged += new SizeChangedEventHandler(element_SizeChanged);
            }
        }

        void element_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            FrameworkElement element = AssociatedObject as FrameworkElement;
            element.Width = element.Height * AspectRatio;
        }

        protected override void Invoke(object parameter)
        {
        }
    }
}

The layout requires some work as self resizing elements (of type path) do some very weird things depending on their parent container. I had to use ViewBoxes as the parent of the paths, combined with the behaviours to get the desired result:

alt text

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
    <Viewbox>
            <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 97.1985,101.669L 104.824,95.0005C 105.574,94.3338 106.921,93.8627 107.824,93.9171L 107.824,101.667L 97.1985,101.669 Z " UseLayoutRounding="False" HorizontalAlignment="Left">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseLeftButtonDown">
                        <local:FixedAspectRatioBehavior/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Path>
        </Viewbox>
    <Grid Width="Auto" Background="#FFFF0D0D" Grid.ColumnSpan="1" Grid.Column="1">
        <Rectangle Grid.Column="1" Fill="#FFD21F1F"/>
        <ContentControl Grid.Column="1" x:Name="HeaderTopSelected" FontSize="{TemplateBinding Control.FontSize}" Foreground="{TemplateBinding Control.Foreground}" IsTabStop="False" Cursor="{TemplateBinding FrameworkElement.Cursor}" HorizontalAlignment="{TemplateBinding FrameworkElement.HorizontalAlignment}" VerticalAlignment="{TemplateBinding FrameworkElement.VerticalAlignment}"/>
        <TextBlock TextWrapping="Wrap" FontSize="16"><Run Text="This is just a very string to see "/><LineBreak/><Run Text="what happens  when we get to a size where the container should get larger than the default size"/></TextBlock>
    </Grid>
    <Viewbox Grid.Column="2">
        <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 118.714,101.678L 111.088,95.0097C 110.338,94.343 108.991,93.8719 108.088,93.9264L 108.088,101.676L 118.714,101.678 Z " UseLayoutRounding="False" d:LayoutOverrides="VerticalAlignment">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseLeftButtonDown">
                    <local:FixedAspectRatioBehavior/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Path>
    </Viewbox>
        </Grid>

Take 1 (obsolete now, as is 2 below):

The width of a path does not push along items in a stack panel. In that respect it's width is useless except to scale the item.

To get the effect you wanted, group each path into a grid. The size problem then goes away.

alt text

Apologies for turning your rectangle horrible red to show it clearly :)

alt text

XAML below:

<StackPanel Orientation="Horizontal" Width="Auto">
    <Grid>
        <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 97.1985,101.669L 104.824,95.0005C 105.574,94.3338 106.921,93.8627 107.824,93.9171L 107.824,101.667L 97.1985,101.669 Z " UseLayoutRounding="False" d:LayoutOverrides="Width"/>
    </Grid>
    <Grid Width="100" Background="#FFFF0D0D">
        <Rectangle Grid.Column="1" Fill="#FFD21F1F"/>
        <ContentControl Grid.Column="1" x:Name="HeaderTopSelected" FontSize="{TemplateBinding Control.FontSize}" Foreground="{TemplateBinding Control.Foreground}" IsTabStop="False" Cursor="{TemplateBinding FrameworkElement.Cursor}" HorizontalAlignment="{TemplateBinding FrameworkElement.HorizontalAlignment}" VerticalAlignment="{TemplateBinding FrameworkElement.VerticalAlignment}"/>
    </Grid>
    <Grid>
        <Path Stretch="UniformToFill" Fill="#FF000000" Data="F1 M 118.714,101.678L 111.088,95.0097C 110.338,94.343 108.991,93.8719 108.088,93.9264L 108.088,101.676L 118.714,101.678 Z " UseLayoutRounding="False" d:LayoutOverrides="Width"/>
    </Grid>
</StackPanel>

Take 2 (also obsolete now, see take 3 at the top):

If you require fixed end widths, use a grid instead of a stack panel (XAML below).

alt text

If you require something else, please provide a couple of screen shots of the desired effect.

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
    <Path Stretch="Fill" Fill="#FF000000" Data="F1 M 97.1985,101.669L 104.824,95.0005C 105.574,94.3338 106.921,93.8627 107.824,93.9171L 107.824,101.667L 97.1985,101.669 Z " UseLayoutRounding="False" d:LayoutOverrides="Width"/>
    <Grid Width="Auto" Background="#FFFF0D0D" Grid.ColumnSpan="1" Grid.Column="1">
        <Rectangle Grid.Column="1" Fill="#FFD21F1F"/>
        <ContentControl Grid.Column="1" x:Name="HeaderTopSelected" FontSize="{TemplateBinding Control.FontSize}" Foreground="{TemplateBinding Control.Foreground}" IsTabStop="False" Cursor="{TemplateBinding FrameworkElement.Cursor}" HorizontalAlignment="{TemplateBinding FrameworkElement.HorizontalAlignment}" VerticalAlignment="{TemplateBinding FrameworkElement.VerticalAlignment}" Content="Hello there.... this is a long string to see what happens"/>
    </Grid>
    <Path Stretch="Fill" Fill="#FF000000" Data="F1 M 118.714,101.678L 111.088,95.0097C 110.338,94.343 108.991,93.8719 108.088,93.9264L 108.088,101.676L 118.714,101.678 Z " UseLayoutRounding="False" d:LayoutOverrides="Width" Grid.Column="2"/>
        </Grid>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文