2

我想实现类似的东西

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

适应小屏幕,如

|图片 (100%)|
|文字(100%|

我有以下带有 AdaptiveTrigger 和 Grid 的解决方案。

<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 Apps 提供的新 Realtive Panel 是否有类似的解决方案?

4

1 回答 1

2

让我们应用我对 x:Null 的想法。这就是我认为你的意思是如何解决这个问题。除了使用 RelativePanel 的图像有一个奇怪的行为,但我添加了一个 MaxHeight,如果需要,可以用文本控件的 ActualHeight 绑定替换:

<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>

诀窍是将事物设置为 {x:Null} 它给出了一个奇怪的警告,但它有效,我还将用它更新我的代码项目文章。

我希望是您正在寻找的答案。

更新:RelativeSizes:

1.- 我创建自定义附加属性以便能够设置容器的相对大小:

    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;
        }
    }
    }

2.- 有了它,您可以设置:

 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 ..." />

UPDATE2:自定义附加属性

XAML:

<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 });
        }
    }
}

这是此自定义附加属性的解决方案,您可以适应更多自定义附加属性,在命名空间中使用反射并获取所有并按名称查找,但这已经足够了。

于 2015-08-06T10:49:55.947 回答