使用 RelativePanel 和 VisualStateManager 构建自适应布局

Building Adaptative Layout with RelativePanel and VisualStateManager

我尝试在嵌入 flipview 的用户控件中使用 VisualStateManager。但是下面的代码不起作用,尽管它看起来确实像

中提到的代码
   <UserControl
        x:Class="JintekiArchives.Views.CardDetailsControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:JintekiArchives"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">

        <Grid>
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="AdaptiveVisualStateGroup">
                    <VisualState x:Name="VisualStateNarrow">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="0" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="descriptionPanel.(RelativePanel.Below)" Value="imageBorder" />
                            <Setter Target="textPanel.(RelativePanel.Below)" Value="descriptionPanel" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="VisualStateNormal">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="521" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="descriptionPanel.(RelativePanel.Below)" Value="imageBorder" />
                            <Setter Target="textPanel.(RelativePanel.Below)" Value="descriptionPanel" />
                        </VisualState.Setters>
                    </VisualState>
                    <VisualState x:Name="VisualStateWide">
                        <VisualState.StateTriggers>
                            <AdaptiveTrigger MinWindowWidth="1200" />
                        </VisualState.StateTriggers>
                        <VisualState.Setters>
                            <Setter Target="descriptionPanel.(RelativePanel.RightOf)" Value="imageBorder" />
                            <Setter Target="textPanel.(RelativePanel.RightOf)" Value="descriptionPanel" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>

            <RelativePanel Margin="20">
                <RelativePanel.Background>
                    <ImageBrush x:Name="backgroundGrid" ImageSource="{Binding FactionImage}" Opacity="0.1" />
                </RelativePanel.Background>
                <StackPanel x:Name="titlePanel" Orientation="Horizontal" Margin="24"
                        RelativePanel.AlignTopWithPanel="True" 
                        RelativePanel.AlignLeftWithPanel="True" 
                        RelativePanel.AlignRightWithPanel="True">
                    <TextBlock FontSize="48" FontWeight="SemiBold" Text="{Binding Title}"></TextBlock>
                </StackPanel>
                <StackPanel Name="imageBorder" Width="300" Height="420" Margin="24, 24"
                        RelativePanel.Below="titlePanel" 
                        RelativePanel.AlignLeftWithPanel="True" 
                        RelativePanel.AlignRightWithPanel="false">
                    <Image Source="{Binding ImageSrc}" Stretch="None"/>
                </StackPanel>
                <StackPanel Name="descriptionPanel" Orientation="Vertical" Margin="24, 24"
                        RelativePanel.AlignTopWith="imageBorder" 
                        RelativePanel.RightOf="imageBorder">
                    <StackPanel Orientation="Horizontal" Margin="5">
                        <TextBlock>
                            <Run FontWeight="Bold" Text="Faction : "></Run>
                            <Run Text="{Binding Faction}"></Run>
                        </TextBlock>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="5">
                        <TextBlock>
                            <Run FontWeight="Bold" Text="Set : "></Run>
                            <Run Text="{Binding Set}"></Run>
                        </TextBlock>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="5">
                        <TextBlock>
                            <Run FontWeight="Bold" Text="Type : "></Run>
                            <Run Text="{Binding Type}"></Run>
                        </TextBlock>
                    </StackPanel>
                </StackPanel>
                <StackPanel Name="textPanel" Orientation="Vertical" Margin="24,24"
                        RelativePanel.AlignTopWith="imageBorder" 
                        RelativePanel.RightOf="descriptionPanel">
                    <StackPanel Orientation="Horizontal" Margin="5">
                        <TextBlock Width="600" TextWrapping="Wrap" TextTrimming="WordEllipsis" Text="{Binding Text}"></TextBlock>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" Margin="5">
                        <TextBlock Width="600" TextWrapping="Wrap" TextTrimming="WordEllipsis" FontStyle="Italic" Text="{Binding Flavor}">
                        </TextBlock>
                    </StackPanel>
                    <StackPanel Padding="5" Orientation="Horizontal" Margin="5">
                        <TextBlock>
                            <Run Text="Illustrated by "></Run>
                            <Run Text="{Binding Illustrator}"></Run>
                        </TextBlock>
                    </StackPanel>
                </StackPanel>
            </RelativePanel>
        </Grid>
    </UserControl>

这里的问题与布局中的 Conflicting relationshipsRelativePanel 有关。

If you set multiple relationships that target the same edge of an element, you might have conflicting relationships in your layout as a result. When this happens, the relationships are applied in the following order of priority:

The panel-center alignment properties (AlignVerticalCenterWith, AlignHorizontalCenterWithPanel, ...) are typically used independently of other constraints and are applied if there is no conflict.

The HorizontalAlignment and VerticalAlignment properties on UI elements are applied after relationship properties are evaluated and applied. These properties control the placement of the element within the available size for the element, if the desired size is smaller than the available size.

所以AlignTopWith的优先级高于Below。在您的代码中,您在 descriptionPaneltextPanel 中将 RelativePanel.AlignTopWith 设置为 imageBorder。因此 VisualState 中的 descriptionPanel.(RelativePanel.Below) 之类的设置将不起作用。

要解决此问题,我建议您 删除 descriptionPaneltextPanelRelativePanel 的附加属性,只在 VisualState 中设置这些附加属性而不使用 AlignTopWith.

由于我不确定你想要的布局是什么,这里我只使用两种视觉状态例如:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="AdaptiveVisualStateGroup">
        <VisualState x:Name="VisualStateNarrow">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="0" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="descriptionPanel.(RelativePanel.Below)" Value="imageBorder" />
                <Setter Target="textPanel.(RelativePanel.Below)" Value="descriptionPanel" />
            </VisualState.Setters>
        </VisualState>
        <VisualState x:Name="VisualStateWide">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="1200" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="descriptionPanel.(RelativePanel.Below)" Value="titlePanel" />
                <Setter Target="descriptionPanel.(RelativePanel.RightOf)" Value="imageBorder" />
                <Setter Target="textPanel.(RelativePanel.Below)" Value="titlePanel" />
                <Setter Target="textPanel.(RelativePanel.RightOf)" Value="descriptionPanel" />
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>