如何在UWP中更简洁高效地正确修改控件样式?
UWP控件样式批量切换优化方案
你目前逐个给控件设置Style的写法重复度高,后续新增控件还要同步修改VisualState配置,维护成本高,下面给出两种可直接落地的简化方案:
方案1:使用值转换器绑定样式,移除冗余Setter
直接将所有控件的Style属性绑定到同一个IsOfferSO字段,通过转换器自动返回对应样式,完全不需要在VisualState里写一堆Setter:
第一步:实现布尔转样式的转换器
public class BoolToStyleConverter : IValueConverter { public Style TrueStyle { get; set; } public Style FalseStyle { get; set; } public object Convert(object value, Type targetType, object parameter, string language) { if (value is bool isTrue) { // 传Reverse参数时反转判断逻辑,适配第二个反选的Offer项 if (parameter as string == "Reverse") isTrue = !isTrue; return isTrue ? TrueStyle : FalseStyle; } return FalseStyle; } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } }
第二步:在页面资源中声明转换器实例
<Page.Resources> <!-- Offer Grid用转换器 --> <local:BoolToStyleConverter x:Key="OfferGridStyleConverter" TrueStyle="{StaticResource SelectedOffer}" FalseStyle="{StaticResource UnSelectedOffer}"/> <!-- 文本控件用转换器 --> <local:BoolToStyleConverter x:Key="OfferTextStyleConverter" TrueStyle="{StaticResource SelectedTxtBlock}" FalseStyle="{StaticResource UnSelectedTxtBlock}"/> </Page.Resources>
第三步:控件直接绑定样式,删除原有VisualState里的所有Setter
<Grid x:Name="gridOffer1" Style="{Binding IsOfferSO, Converter={StaticResource OfferGridStyleConverter}}"> <TextBlock x:Name="durationOffer1" Style="{Binding IsOfferSO, Converter={StaticResource OfferTextStyleConverter}}"/> <TextBlock x:Name="priceOffer1" Style="{Binding IsOfferSO, Converter={StaticResource OfferTextStyleConverter}}"/> </Grid> <Grid x:Name="gridOffer2" Style="{Binding IsOfferSO, Converter={StaticResource OfferGridStyleConverter}, ConverterParameter=Reverse}"> <TextBlock x:Name="durationOffer2" Style="{Binding IsOfferSO, Converter={StaticResource OfferTextStyleConverter}, ConverterParameter=Reverse}"/> <TextBlock x:Name="priceOffer2" Style="{Binding IsOfferSO, Converter={StaticResource OfferTextStyleConverter}, ConverterParameter=Reverse}"/> </Grid>
如果使用{x:Bind}语法,UWP支持直接对布尔值取反,不需要传Reverse参数,写法更简洁:{x:Bind !IsOfferSO, Converter={...}}
方案2:使用列表控件承载选项,利用自带选中状态切换样式
你的场景本质是二选一的选项组,直接用ListView承载两个Offer项,依托控件自带的选中状态自动切换样式,后续加新选项不需要修改任何状态逻辑:
<ListView ItemsSource="{x:Bind OfferList}" SelectedIndex="{Binding IsOfferSO, Converter={StaticResource BoolToIntConverter}}"> <ListView.ItemContainerStyle> <Style TargetType="ListViewItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ListViewItem"> <Grid x:Name="RootGrid" Style="{StaticResource UnSelectedOffer}"> <TextBlock x:Name="DurationTxt" Style="{StaticResource UnSelectedTxtBlock}" Text="{Binding Duration}"/> <TextBlock x:Name="PriceTxt" Style="{StaticResource UnSelectedTxtBlock}" Text="{Binding Price}"/> </Grid> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="SelectionStates"> <VisualState x:Name="Selected"> <VisualState.Setters> <Setter Target="RootGrid.Style" Value="{StaticResource SelectedOffer}"/> <Setter Target="DurationTxt.Style" Value="{StaticResource SelectedTxtBlock}"/> <Setter Target="PriceTxt.Style" Value="{StaticResource SelectedTxtBlock}"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </ControlTemplate> </Setter.Value> </Setter> </Style> </ListView.ItemContainerStyle> </ListView>
这种方案所有样式逻辑只需要写一次,适配任意数量的Offer选项,可维护性最高。
内容的提问来源于stack exchange,提问作者VerSsuSs
相关产品推荐
相关产品推荐

