使用UWP应用程序的XAML中具有RelativePanel的UI元素的相对宽度

使用UWP应用程序的XAML中具有RelativePanel的UI元素的相对宽度,xaml,windows-store-apps,windows-10,uwp,Xaml,Windows Store Apps,Windows 10,Uwp,我想实现这样的目标 |图像(40%宽度)|文本(60%宽度)| 这适用于小屏幕,如 |图像(100%)| |文本(100%)| 我用AdaptiveTrigger和网格得到了以下解决方案 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup

我想实现这样的目标

|图像(40%宽度)|文本(60%宽度)|

这适用于小屏幕,如

|图像(100%)|
|文本(100%)|

我用AdaptiveTrigger和网格得到了以下解决方案

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateGroup">
            <VisualState x:Name="NarrowView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="Image.(Grid.ColumnSpan)" Value="2" />
                    <Setter Target="Text.(Grid.Row)" Value="1" />
                    <Setter Target="Text.(Grid.Column)" Value="0" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="WideView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="860" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="Image.(Grid.ColumnSpan)" Value="1" />
                    <Setter Target="Text.(Grid.Row)" Value="0" />
                    <Setter Target="Text.(Grid.Column)" Value="1" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*"/>
        <ColumnDefinition Width="3*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Image x:Name="Image" Source="../Image.jpg" />
    <TextBlock x:Name="Text" Grid.Column="1" TextWrapping="WrapWholeWords" Text="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum." />
    <Border Grid.Row="2" Grid.ColumnSpan="2" Background="Blue">
        <TextBlock Text="Other Content" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
</Grid>


我的问题:
Windows 10 UWP应用程序提供的新Realtive Panel是否有类似的解决方案?

让我们应用我对x:Null的想法。这就是我认为你的意思。此外,使用RelativePanel的图像有一种奇怪的行为,但我添加了一个MaxHeight,可以用实际高度绑定来代替f文本控件(如果需要):

<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="VisualStateGroup">
            <VisualState x:Name="NarrowView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="Text.(RelativePanel.Below)" Value="Image" />
                    <Setter Target="Content.(RelativePanel.Below)" Value="Text" />

                    <Setter Target="Text.(RelativePanel.RightOf)" Value="{x:Null}" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="WideView">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="860" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="Text.(RelativePanel.Below)" Value="{x:Null}" />

                    <Setter Target="Text.(RelativePanel.RightOf)" Value="Image" />
                    <Setter Target="Content.(RelativePanel.Below)" Value="Image" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Image x:Name="Image" Source="ms-appx:///Assets/StoreLogo.png" MaxWidth="200" />
    <TextBlock x:Name="Text" RelativePanel.Below="Image"  TextWrapping="WrapWholeWords" Text="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum." />
    <Border x:Name="Content" Background="Blue" RelativePanel.Below="Text" >
    <TextBlock Text="Other Content" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
</RelativePanel>


这是一个用于此自定义附加属性的解决方案,您可以使用更多自定义附加属性,使用命名空间中的反射和“全部获取”和“按名称查找”,但这已经足够了。

正如您现在可能看到的,RelativePanel允许您将子元素相对于彼此和面板本身进行定位。移动子元素很容易xt位于图像下方,而不是图像右侧,但我认为你不能像网格那样指定元素如何占用空间,因此你的解决方案在我看来相当不错……在这种情况下,使用
网格
没有错。但是我如何用40%和60%来解决相对宽度?没有必要,所以我标记为已解决-将代码隐藏在脑海中;)
    public class RelativeSize : DependencyObject
    {
    private static List<FrameworkElement> elements = new List<FrameworkElement>();

    private static FrameworkElement Container = null;
    private static bool containerready = false;

    public static void SetContainer(UIElement element, FrameworkElement value)
    {
        element.SetValue(ContainerProperty, value);
    }
    public static FrameworkElement GetContainer(UIElement element)
    {
        return (FrameworkElement)element.GetValue(ContainerProperty);
    }
    public static readonly DependencyProperty ContainerProperty =
        DependencyProperty.RegisterAttached("Container", typeof(FrameworkElement), typeof(RelativeSize), new PropertyMetadata(null,ContainerChanged));

    private static void ContainerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Container = (e.NewValue as FrameworkElement);
        Container.SizeChanged += (sc, ec) =>
            {

                foreach (var element in elements)
                {
                    var rWidth = element.GetValue(RelativeSize.WidthProperty);

                    if (rWidth != null)
                    {
                        element.Width = (double)rWidth * Container.ActualWidth;
                    }
                }
            };
        containerready = true;
    }

    public static void SetWidth(UIElement element, double value)
    {
        element.SetValue(WidthProperty, value);
    }
    public static double GetWidth(UIElement element)
    {
        return (double)element.GetValue(WidthProperty);
    }
    public static readonly DependencyProperty WidthProperty =
      DependencyProperty.RegisterAttached("Width", typeof(double), typeof(RelativeSize), new PropertyMetadata(0.0, WidthChanged));

    private static async void WidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        while (!containerready)
            await Task.Delay(60);

        var fe = d as FrameworkElement;
        if(fe!=null)
        {
            if (!elements.Contains(fe))
                elements.Add(fe);
            fe.Width = (double)e.NewValue * Container.ActualWidth;
        }
    }
    }
 xmlns:p="using:Controls.Views.Properties"
 <Image x:Name="Image" p:RelativeSize.Container="{Binding ElementName=Root}" p:RelativeSize.Width="0.4"  Source="ms-appx:///Assets/StoreLogo.png"  />
    <TextBlock x:Name="Text" RelativePanel.Below="Image" p:RelativeSize.Width="0.6" HorizontalAlignment="Left" TextWrapping="WrapWholeWords" Text="Lorem ipsum ..." />
<VisualStateGroup x:Name="VisualStateGroup" CurrentStateChanged="VisualStateGroup_CurrentStateChanged">
private void VisualStateGroup_CurrentStateChanged(object sender, VisualStateChangedEventArgs e)
{
    foreach (var sbase in e.NewState.Setters)
    {
        var setter = sbase as Setter;
        var spath = setter.Target.Path.Path;
        var element = setter.Target.Target as FrameworkElement;

        if (spath.Contains(nameof(RelativeSize)))
        {
            string property = spath.Split('.').Last().TrimEnd(')');

            var prop = typeof(RelativeSize).GetMethod($"Set{property}");

            prop.Invoke(null, new object[] { element, setter.Value });
        }
    }
}