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
TextBlockfuera deDataTemplatey establecerVisibility="Collapsed"<TextBlock Name="SetFontSize" Visibility="Collapsed"/>Nota: También puede usar
BindableValueHolderlugar de esto y establecer la propiedad Value de este usandoAdaptiveTrigger.<helpers:BindableValueHolder x:Name="SetFontSize"/>Utilice
AdaptiveTriggerpara cambiar elFontSizedeFontSizede 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
FontSizedelTextBlockdentro delDataTemplatealTextBlockexterno<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>