XAML 将ICommand的CanExecute绑定到FontIcon的前景颜色

vecaoik1  于 2023-04-18  发布在  其他
关注(0)|答案(2)|浏览(132)

问题

我有一个Button,其命令是ToggleMode,在这个按钮是一个FontIcon和一个TextBlock.
在Styles.xaml中,当启用Button时,我将Button的前景色设置为白色,如果禁用按钮,则设置为浅灰色。这导致当禁用Button时,Textblocks前景色正确更改,因为ToggleMode.CanExecute()返回false。然而,FontIcons正常颜色为浅蓝色。我使用Foreground属性设置。当Button被禁用时,颜色应该更改为淡蓝色,以改善按钮被禁用的印象。

代码示例

布尔转换器

<local:BooleanConverter x:Key="CanExecuteToIconColorConverter">
        <local:BooleanConverter.True>
            <SolidColorBrush Color="{ThemeResource VividSkyBlueColor}" />
        </local:BooleanConverter.True>
        <local:BooleanConverter.False>
            <SolidColorBrush Color="{ThemeResource PaleVividSkyBlueColor}" />
        </local:BooleanConverter.False>
    </local:BooleanConverter>

按钮

<Button Grid.Row="0" Width="150" Padding="10"
            Command="{x:Bind ToggleMode, Mode=OneWay}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="3*"/>
            </Grid.ColumnDefinitions>
            <FontIcon FontSize="20" Grid.Column="0"
                      Glyph="{StaticResource mdi_toggle_off}"
                      FontFamily="{StaticResource MaterialDesignIconsOutlined}"
                      Foreground="{ThemeResource VividSkyBlueColor}"/>
            <TextBlock Grid.Column="1" Margin="10,0,0,0" Text="Toggle"/>
        </Grid>
    </Button>

我所尝试的

我尝试使用这里给出的通用BooleanConverter:如何反转BooleanToVisibilityConverter?设置一个SolidColorBrush,其中浅蓝色为True Value,淡蓝色为False Value,并将FontIconForeground属性绑定到命令,但这不起作用。
之后,我尝试订阅命令的CanExecuteChanged事件,将新值保存在私有字段中并绑定到该字段,但这并不起作用,因为在初始化视图时,此命令仍然为空。
我的下一个猜测是订阅命令的属性更改事件,当这个命令被触发时,命令不应该再为null,我应该能够订阅事件,但这似乎是一个很大的锅炉代码,特别是如果我有各种命令,我需要这样做。
我怎样才能更容易地做到这一点?

Edit 1如何将命令绑定到FontIcon

<FontIcon FontSize="20" Grid.Column="0"
          Glyph="{StaticResource mdi_toggle_off}"
          FontFamily="{StaticResource MaterialDesignIconsOutlined}"
          Foreground="{x:Bind ToggleCommand, Mode=OneWay, Converter={StaticResource CanExecuteToIconColorConverter}}"/>

对我有用的

跟随@AndrewKeepCoding的回答,我发现只绑定到按钮的IsEnabled属性,而不是绑定到命令本身:

<Button Grid.Row="0" Width="150" Padding="10"
        Command="{x:Bind ToggleMode, Mode=OneWay}"
        x:Name="ToggleModeButton">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <FontIcon FontSize="20" Grid.Column="0"
                  Glyph="{StaticResource mdi_toggle_off}"
                  FontFamily="{StaticResource MaterialDesignIconsOutlined}"
                  Foreground="{x:Bind ToggleModeButton.IsEnabled, Mode=OneWay, Converter={StaticResource CanExecuteToIconColorConverter}}"/>
        <TextBlock Grid.Column="1" Margin="10,0,0,0" Text="Toggle"/>
    </Grid>
</Button>
laximzn5

laximzn51#

让我向您展示另一种使用ValueConverter实现此目的的方法。

布尔转刷转换器.cs

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Media;
using System;

namespace FontIconExample;

public class BooleanToBrushConverter : DependencyObject, IValueConverter
{
    public static readonly DependencyProperty TrueBrushProperty =
        DependencyProperty.Register(
            nameof(TrueBrush),
            typeof(Brush),
            typeof(BooleanToBrushConverter),
            new PropertyMetadata(default));

    public static readonly DependencyProperty FalseBrushProperty =
        DependencyProperty.Register(
            nameof(FalseBrush),
            typeof(Brush),
            typeof(BooleanToBrushConverter),
            new PropertyMetadata(default));

    public Brush TrueBrush
    {
        get => (Brush)GetValue(TrueBrushProperty);
        set => SetValue(TrueBrushProperty, value);
    }

    public Brush FalseBrush
    {
        get => (Brush)GetValue(FalseBrushProperty);
        set => SetValue(FalseBrushProperty, value);
    }

    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return (bool)value is true
            ? TrueBrush
            : FalseBrush;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

MainPageViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace FontIconExample;

public partial class ViewModel : ObservableObject
{
    [RelayCommand(CanExecute = nameof(CanToggleMode))]
    private void ToggleMode()
    {
        CanToggleMode = false;
    }

    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(ToggleModeCommand))]
    private bool canToggleMode = true;
}

MainPage.xaml

<Page
    x:Class="FontIconExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:FontIconExample"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">
    <Page.DataContext>
        <local:ViewModel x:Name="ViewModel" />
    </Page.DataContext>
    <Page.Resources>
        <local:BooleanToBrushConverter
            x:Key="BooleanToBrushConverter"
            FalseBrush="LightGreen"
            TrueBrush="SkyBlue" />
    </Page.Resources>

    <Grid>
        <Button
            x:Name="ToggleModeButton"
            Grid.Row="0"
            Width="150"
            Padding="10"
            Command="{x:Bind ViewModel.ToggleModeCommand, Mode=OneWay}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="3*" />
                </Grid.ColumnDefinitions>
                <FontIcon
                    Grid.Column="0"
                    FontFamily="Segoe MDL2 Assets"
                    FontSize="20"
                    Foreground="{x:Bind ToggleModeButton.IsEnabled, Mode=OneWay, Converter={StaticResource BooleanToBrushConverter}}"
                    Glyph="&#xE790;" />
                <TextBlock
                    Grid.Column="1"
                    Margin="10,0,0,0"
                    Text="Toggle" />
            </Grid>
        </Button>
    </Grid>
</Page>
3vpjnl9f

3vpjnl9f2#

根据我的经验,FontIcon有点不稳定,因为在某些方面它的行为并不符合预期。修改FontIcon的颜色可能适合您的特定情况,(如果您可以让它工作),但在更复杂的情况下,您可能有一个复杂的控件,必须看起来禁用,它不会工作。
在这些情况下,我更喜欢避免修改单个元素的颜色,而是执行以下操作之一:

  • 修改整个控件的透明度
  • 在该控件的顶部添加另一个几乎透明但不完全透明的控件,以洗掉基础控件的颜色。

当某个深蓝色稍微透明时(或者当它被白色但几乎透明的阴影覆盖时),它将显示为浅蓝色,并且深橙子也将显示为浅橙色等。

相关问题