XAML Определение размера пути и позиционирование - PullRequest
1 голос
/ 25 августа 2010

Я пытаюсь разработать шаблон для 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

1 Ответ

3 голосов
/ 25 августа 2010

Взять 3 (теперь мы знаем, что это за требование):

В основном, чтобы получить желаемый эффект, вам нужны 2 боковые части, чтобы изменить их ширину, если их высота изменяется, чтобы сохранить фиксированное соотношение сторон. Это заставит родительский контейнер расширяться, так как фактический контент становится выше, а стороны становятся выше, чтобы соответствовать. ни один из контейнеров (включая ViewBox) не работает именно так.

Вы можете использовать пользовательский контейнер для этого, но предпочтительным решением будет создание поведения, которое сохраняет соотношение сторон его объекта при изменении высоты. Мы назовем его 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)
        {
        }
    }
}

Макет требует некоторой работы, так как саморазмеряющиеся элементы (типа path) делают очень странные вещи в зависимости от их родительского контейнера. Мне пришлось использовать 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>

Возьмите 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>
...