2015-08-06 1 views
2

Я хочу, чтобы реализовать что-то вродеОтносительная ширина для элементов пользовательского интерфейса с RelativePanel в XAML с UWP Apps

| Image (40% Ширина) | Текст (60% Ширина) |

, который адаптируется к маленьким экранам, как

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

Мой вопрос:.
Есть ли подобное решение с новым Realtive панели, представленной Windows 10 UWP-приложения?

+0

Как вы, вероятно, теперь RelativePanel позволяет размещать дочерние элементы относительно друг друга и самой панели. Было бы легко перемещать текст под изображением вместо правого изображения, но я не думаю, что вы можете указать, как элементы занимают пространство, как вы можете сделать с сеткой, поэтому ваше решение выглядит довольно хорошо для меня ... –

+0

В этом случае нет ничего плохого в использовании «Grid». –

ответ

1

Давайте применим свои мысли о 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}, это дает странное предупреждение, но оно работает, я также обновляю мою статью с кодом.

Надеюсь, это ответ, который вы искали.

UPDATE: The 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 }); 
     } 
    } 
} 

Это решение для этого пользовательского вложенного свойства, и вы можете адаптировать с большим количеством пользовательских прикрепленные свойства, используя отражение в пространстве имен и получить все и найти по имени, но этого достаточно.

+0

Но как решить релятивную ширину с 40% и 60%? –

+0

Я могу добавить код позади, если вы хотите –

+0

Нет необходимости в этом, поэтому я отмечаю, как решено - с учетом кода;) –

Смежные вопросы