c# - developing - Cómo usar VisualState AdaptiveTrigger para cambiar ListView Item FontSize
uwp samples (2)
Estoy usando Visual State Adaptive Trigger para cambiar el aspecto de la página en función de la resolución de pantalla efectiva. Esto funciona muy bien, pero no puedo hacer que funcione para elementos ListView.
Mi ListView se ve así:
<ListView x:Name="listView" >
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="20" Text="{Binding MyItem}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Puedo cambiar el tamaño de la fuente TextBlock estáticamente en XAML. Pero no sé cómo hacer referencia a esto en el objetivo setter de VisualState. Al ser hijo generado automáticamente, no puedo darle un nombre a TextBlock. Mi código Visual State está debajo. He puesto ??? donde quiero referirme al elemento ListView TextBlock FontSize.
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="NormalStateReadView">
<!-- VisualState to be triggered when window width is <720 effective pixels -->
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="???" Value="20" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup>
<VisualState x:Name="NormalStateReadView">
<!-- VisualState to be triggered when window width is >=720 effective pixels -->
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="???" Value="30" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
Cualquier ayuda apreciada.
Tendrá que envolver su plantilla dentro de un UserControl
para que los desencadenantes de adaptación funcionen; también los estados visuales deben ir también dentro de la plantilla y asegurarse de que estén debajo del primer elemento secundario directo (es decir, Grid
) del UserControl
. Veo que ha definido dos grupos visuales de estado, pero realmente solo necesita uno.
<ListView.ItemTemplate>
<DataTemplate>
<UserControl>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Title.(TextBlock.FontSize)" Value="24" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="Title.(TextBlock.FontSize)" Value="36" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="Title" Text="{Binding Property1}" />
</Grid>
</UserControl>
</DataTemplate>
</ListView.ItemTemplate>
Actualizar
Esto es lo que creo que es una solución mucho más flexible. Necesita un poco de código para configurar, pero el resultado es que obtienes un código limpio, reutilizable y legible.
La idea es obtener una referencia del VisualStateGroup
nivel superior que se define fuera de ListView
, principalmente en el nivel de Page
.
Luego, cree tres VisualState
s (es decir, Estrecho , Normal y Ancho ) y conéctelos a un nuevo VisualStateGroup
que debería pertenecer al primer elemento secundario de UserControl
.
Una vez que hemos hecho referencia a estos dos VisualStateGroup
, podemos monitorear el CurrentStateChanged de nivel superior y actualizar el estado en el segundo en consecuencia.
Toda la lógica anterior puede ser envuelta por un Behavior
del paquete Nuget Behavior
de UWP XAML .
Una vez que el Behavior
en su lugar, puede definir sus estados internos tan fácil como -
<DataTemplate>
<UserControl>
<Interactivity:Interaction.Behaviors>
<local:VisualStateInTemplateBehavior ParentVisualStateGroup="{Binding ElementName=AdaptiveVisualStates}">
<local:VisualStateInTemplateBehavior.NarrowState>
<VisualState x:Name="Narrow">
<VisualState.Setters>
<Setter Target="Title.(TextBlock.FontSize)" Value="24" />
</VisualState.Setters>
</VisualState>
</local:VisualStateInTemplateBehavior.NarrowState>
<local:VisualStateInTemplateBehavior.NormalState>
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Target="Title.(TextBlock.FontSize)" Value="32" />
</VisualState.Setters>
</VisualState>
</local:VisualStateInTemplateBehavior.NormalState>
<local:VisualStateInTemplateBehavior.WideState>
<VisualState x:Name="Wide">
<VisualState.Setters>
<Setter Target="Title.(TextBlock.FontSize)" Value="40" />
</VisualState.Setters>
</VisualState>
</local:VisualStateInTemplateBehavior.WideState>
</local:VisualStateInTemplateBehavior>
</Interactivity:Interaction.Behaviors>
Demo de trabajo
Siéntase libre de echar un vistazo a una muestra de trabajo aquí .
No podemos usar AdaptiveTrigger
para un elemento dentro de DataTemplate
. Debe usar UserControl para hacerlo. Esta respuesta puede ayudarte. Si desea un video tutorial , este video puede ayudarlo. Pero tengo una pequeña solución para eso.
Aquí está mi método:
Crear un
TextBlock
fuera deDataTemplate
y establecerVisibility="Collapsed"
<TextBlock Name="SetFontSize" Visibility="Collapsed"/>
Nota: También puede usar
BindableValueHolder
lugar de esto y establecer la propiedad Value de este usandoAdaptiveTrigger
.<helpers:BindableValueHolder x:Name="SetFontSize"/>
Utilice
AdaptiveTrigger
para cambiar elFontSize
deFontSize
de esteTextBlock
<VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualState x:Name="NormalStateReadView"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="SetFontSize.FontSize" Value="20" /> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup> <VisualState x:Name="WideStateReadView"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="720" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="SetFontSize.FontSize" Value="30" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups>
DataBind el
FontSize
delTextBlock
dentro delDataTemplate
alTextBlock
externo<TextBlock FontSize="{Binding Path=FontSize, ElementName=SetFontSize}"/>
Aquí está tu código:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="NormalStateReadView">
<!-- VisualState to be triggered when window width is <720 effective pixels -->
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SetFontSize.FontSize" Value="20" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup>
<VisualState x:Name="WideStateReadView">
<!-- VisualState to be triggered when window width is >=720 effective pixels -->
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SetFontSize.FontSize" Value="30" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock Name="SetFontSize" Visibility="Collapsed"/>
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="{Binding Path=FontSize, ElementName=SetFontSize}" Text="{Binding MyItem}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>