samples - Ancho relativo para elementos de interfaz de usuario con RelativePanel en XAML con aplicaciones UWP
uwp vs wpf (1)
Vamos a aplicar mis pensamientos sobre x: nulo. Eso es lo que creo que quieres decir sobre cómo resolver esto. Aparte, hay un comportamiento extraño de la imagen usando RelativePanel, pero agregué un MaxHeight que puede ser reemplazado con el Enlace de Altura Actual del Control de Texto si es necesario:
<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>
El truco es configurar las cosas en {x: Null}, da una advertencia extraña pero funciona, también actualizaré mi artículo de proyecto de código con eso.
Espero que sea la respuesta que estabas buscando.
ACTUALIZACIÓN : los tamaños relativos:
1.- Creo propiedades adjuntas personalizadas para poder establecer el tamaño relativo a un contenedor:
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.- Con eso puedes configurar:
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 ..." />
ACTUALIZACIÓN2 : las propiedades adjuntas personalizadas
XAML:
<VisualStateGroup x:Name="VisualStateGroup" CurrentStateChanged="VisualStateGroup_CurrentStateChanged">
Código:
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 });
}
}
}
Es una solución para esta propiedad adjunta personalizada y puede adaptarse con más propiedades adjuntas personalizadas, utilizando la reflexión en el espacio de nombres y obtener todo y buscar por nombre, pero para esto es suficiente.
Quiero darme cuenta de algo así como
| Imagen (40% de ancho) | Texto (60% de ancho) |
que se adapta a pantallas pequeñas como
| Imagen (100%) |
| Texto (100% |
Tengo la siguiente solución con AdaptiveTrigger y una 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>
Mi pregunta:
¿Hay alguna solución similar con el nuevo Panel de Realidad proporcionado por Windows 10 UWP Apps?