Maui/Xamarin:切换系统主题后AppShell标签未重新渲染问题
问题描述
我的Shell菜单使用以下代码实现FlyoutFooter:
<Shell.FlyoutFooter> <VerticalStackLayout Padding="10,0,0,0" Margin="0,0,0,10" HeightRequest="50"> <Label Text="{Binding UserEmail}" HorizontalOptions="Center" TextColor="{AppThemeBinding Dark=White, Light=Black}" FontFamily="ook" FontSize="Medium"/> <Label Text="{Binding AppVersion, StringFormat='V. {0}'}" TextColor="{AppThemeBinding Dark=White, Light=Black}" FontFamily="ook" HorizontalOptions="Center" FontSize="Medium"/> </VerticalStackLayout> </Shell.FlyoutFooter>
这段代码可正常运行,但切换手机主题后不重启直接返回应用时,FlyoutFooter内的标签文字颜色不会随主题变更。奇怪的是Shell菜单里其他元素都能正确重新渲染。
我尝试通过绑定Appearing事件处理(MVVM模式),代码如下:
<Shell.Behaviors> <MTK:EventToCommandBehavior EventName="Appearing" Command="{Binding ReLoadLogsCommand}"/> </Shell.Behaviors>
但应用恢复时该事件不会触发,此方案无效。请问还有哪些修复方案?
修复方案
以下几种方案可尝试解决该主题切换不更新的问题:
监听主题变更事件,强制刷新绑定上下文
在ViewModel中监听应用主题变更事件,当主题切换时手动重置FlyoutFooter的绑定上下文,触发UI刷新:public YourViewModel() { Application.Current.RequestedThemeChanged += OnRequestedThemeChanged; } private void OnRequestedThemeChanged(object sender, AppThemeChangedEventArgs e) { var mainShell = Application.Current.MainPage as Shell; if (mainShell?.FlyoutFooter is VerticalStackLayout footerLayout) { var currentContext = footerLayout.BindingContext; footerLayout.BindingContext = null; footerLayout.BindingContext = currentContext; } }使用全局样式替代直接绑定
在资源字典中定义适配主题的Label样式,再给FlyoutFooter内的Label应用该样式,主题变更时样式会自动更新:<ResourceDictionary> <Style x:Key="FooterLabelStyle" TargetType="Label"> <Setter Property="TextColor" Value="{AppThemeBinding Dark=White, Light=Black}"/> <Setter Property="FontFamily" Value="ook"/> <Setter Property="FontSize" Value="Medium"/> <Setter Property="HorizontalOptions" Value="Center"/> </Style> </ResourceDictionary>修改FlyoutFooter的Label代码:
<Label Text="{Binding UserEmail}" Style="{StaticResource FooterLabelStyle}"/> <Label Text="{Binding AppVersion, StringFormat='V. {0}'}" Style="{StaticResource FooterLabelStyle}"/>改用FlyoutFooterTemplate定义内容
把FlyoutFooter替换为FlyoutFooterTemplate形式,模板化的内容在主题变更时可能会自动触发重新渲染:<Shell.FlyoutFooterTemplate> <DataTemplate> <VerticalStackLayout Padding="10,0,0,0" Margin="0,0,0,10" HeightRequest="50"> <Label Text="{Binding UserEmail}" HorizontalOptions="Center" TextColor="{AppThemeBinding Dark=White, Light=Black}" FontFamily="ook" FontSize="Medium"/> <Label Text="{Binding AppVersion, StringFormat='V. {0}'}" TextColor="{AppThemeBinding Dark=White, Light=Black}" FontFamily="ook" HorizontalOptions="Center" FontSize="Medium"/> </VerticalStackLayout> </DataTemplate> </Shell.FlyoutFooterTemplate>添加刷新触发器属性
在ViewModel中新增一个用于触发UI刷新的属性,主题变更时更新该属性,通过绑定让Label重新渲染:private int _themeRefreshTrigger; public int ThemeRefreshTrigger { get => _themeRefreshTrigger; set => SetProperty(ref _themeRefreshTrigger, value); } private void OnRequestedThemeChanged(object sender, AppThemeChangedEventArgs e) { ThemeRefreshTrigger++; }给Label添加绑定触发器:
<Label Text="{Binding UserEmail}" TextColor="{AppThemeBinding Dark=White, Light=Black}" FontFamily="ook" FontSize="Medium" HorizontalOptions="Center" Tag="{Binding ThemeRefreshTrigger}"/>
内容的提问来源于stack exchange,提问作者innom
相关产品推荐
相关产品推荐

