在IConverter中使用AppThemeBinding无法响应主题切换的问题求助
解决BoolToColorConverter主题切换不更新颜色的问题
你创建的BoolToColorConverter在应用启动时能根据主题正确显示颜色,但运行中切换主题时,颜色不会自动更新:
- 启动时深色模式效果:

- 启动时浅色模式效果:

- 主题切换后异常效果:

原因是:绑定的触发条件是源属性(CheckBox的IsChecked)变化,而AppThemeBinding更新TrueColor时,并不会触发源属性的变化,因此转换器的Convert方法不会重新执行,导致颜色保持旧值。
以下是两种可行的解决方案:
方法一:改用IMultiValueConverter监听多源变化
将转换器改为实现IMultiValueConverter,同时把FalseColor也改为可绑定属性,这样绑定会监听IsChecked、TrueColor、FalseColor三个值的变化,任意一个变化都会触发颜色更新。
1. 更新转换器代码
public class BoolToColorConverter : BindableObject, IMultiValueConverter { public static readonly BindableProperty TrueColorProperty = BindableProperty.Create(nameof(TrueColor), typeof(Color), typeof(BoolToColorConverter), null, BindingMode.OneWay); public Color TrueColor { get { return (Color)GetValue(TrueColorProperty); } set { SetValue(TrueColorProperty, value); } } public static readonly BindableProperty FalseColorProperty = BindableProperty.Create(nameof(FalseColor), typeof(Color), typeof(BoolToColorConverter), null, BindingMode.OneWay); public Color FalseColor { get { return (Color)GetValue(FalseColorProperty); } set { SetValue(FalseColorProperty, value); } } public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if (values.Length >= 3 && values[0] is bool isChecked) { var trueColor = values[1] as Color ?? Colors.Transparent; var falseColor = values[2] as Color ?? Colors.Transparent; return isChecked ? trueColor : falseColor; } return Colors.Transparent; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
2. 修改XAML中的绑定为MultiBinding
<ContentPage.Resources> <converts:BoolToColorConverter x:Key="ColorConverter" TrueColor="{AppThemeBinding Light=DarkRed, Dark=LightSalmon}" FalseColor="#888" /> </ContentPage.Resources> <VerticalStackLayout> <Label Text="Hello, World!" FontSize="32" HorizontalOptions="Center"> <Label.TextColor> <MultiBinding Converter="{StaticResource ColorConverter}"> <Binding Source="{x:Reference Checky}" Path="IsChecked" /> <Binding Source="{StaticResource ColorConverter}" Path="TrueColor" /> <Binding Source="{StaticResource ColorConverter}" Path="FalseColor" /> </MultiBinding> </Label.TextColor> </Label> <CheckBox x:Name="Checky" /> </VerticalStackLayout>
方法二:监听主题变化强制刷新绑定
如果不想修改为MultiBinding,可以在转换器中订阅应用主题变化事件,当主题切换时,手动触发绑定的刷新:
1. 更新转换器代码
public class BoolToColorConverter : BindableObject, IValueConverter { private readonly List<BindableObject> _targets = new(); public BoolToColorConverter() { Application.Current.RequestedThemeChanged += OnThemeChanged; } public static readonly BindableProperty TrueColorProperty = BindableProperty.Create(nameof(TrueColor), typeof(Color), typeof(BoolToColorConverter), null, BindingMode.OneWay); public Color TrueColor { get { return (Color)GetValue(TrueColorProperty); } set { SetValue(TrueColorProperty, value); } } public static readonly BindableProperty FalseColorProperty = BindableProperty.Create(nameof(FalseColor), typeof(Color), typeof(BoolToColorConverter), null, BindingMode.OneWay); public Color FalseColor { get { return (Color)GetValue(FalseColorProperty); } set { SetValue(FalseColorProperty, value); } } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // 记录绑定目标,用于后续刷新 if (parameter is BindableObject target && !_targets.Contains(target)) { _targets.Add(target); } if (value is bool b && b) { return TrueColor!; } return FalseColor!; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } private void OnThemeChanged(object sender, AppThemeChangedEventArgs e) { // 刷新所有绑定目标的属性 foreach (var target in _targets) { foreach (var binding in target.GetBindableProperties()) { var expression = target.GetBindingExpression(binding); expression?.UpdateTarget(); } } } protected override void Dispose(bool disposing) { if (disposing) { Application.Current.RequestedThemeChanged -= OnThemeChanged; } base.Dispose(disposing); } }
2. 修改XAML绑定,传递目标参数
<Label Text="Hello, World!" TextColor="{Binding Source={x:Reference Checky}, Path=IsChecked, Converter={StaticResource ColorConverter}, ConverterParameter={x:Reference ThisLabel}}" FontSize="32" HorizontalOptions="Center" x:Name="ThisLabel" />
内容的提问来源于stack exchange,提问作者PEK
相关产品推荐
相关产品推荐

