You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI中用MVVM Community ToolKit传递Switch的Sender至ViewModel

在MAUI MVVM中处理多个Switch控件的状态变更

核心原则

MVVM模式下,ViewModel不应直接引用或操作UI控件(比如通过sender获取Switch),而是通过数据绑定同步状态,通过命令处理交互逻辑。以下是具体实现方案:


方案1:绑定IsToggled到ViewModel属性(推荐)

这是最符合MVVM的方式,直接将Switch的状态绑定到ViewModel的布尔属性,在属性的setter中处理状态变更逻辑,无需额外事件。

ViewModel代码

namespace MyProject.ViewModels
{
    public partial class SettingsPageViewModel : BaseViewModel
    {
        private bool _isDarkModeToggled;
        public bool IsDarkModeToggled
        {
            get => _isDarkModeToggled;
            set 
            { 
                SetProperty(ref _isDarkModeToggled, value);
                // 状态变更时直接处理逻辑
                OnDarkModeToggled(value);
            }
        }

        private bool _isNotificationsEnabledToggled;
        public bool IsNotificationsEnabledToggled
        {
            get => _isNotificationsEnabledToggled;
            set 
            { 
                SetProperty(ref _isNotificationsEnabledToggled, value);
                OnNotificationsToggled(value);
            }
        }

        ILogger<SettingsPageViewModel> _logger;
        public SettingsPageViewModel(ILogger<SettingsPageViewModel> logger)
        {
            _logger = logger;
            // 初始化默认状态
            IsDarkModeToggled = true;
            IsNotificationsEnabledToggled = false;
        }

        private void OnDarkModeToggled(bool isEnabled)
        {
            _logger.LogInformation($"暗黑模式已{(isEnabled ? "开启" : "关闭")}");
            // 这里写暗黑模式切换的业务逻辑
        }

        private void OnNotificationsToggled(bool isEnabled)
        {
            _logger.LogInformation($"通知已{(isEnabled ? "开启" : "关闭")}");
            // 这里写通知开关的业务逻辑
        }
    }       
}

XAML代码

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyProject.Views.SettingsPage"
             xmlns:vm="clr-namespace:MyProject.ViewModels"
             x:DataType="vm:SettingsPageViewModel"
             BackgroundColor="{DynamicResource PageBackGround}">

    <ContentPage.Content>
        <StackLayout>
            <!-- 暗黑模式开关 -->
            <Switch IsToggled="{Binding IsDarkModeToggled}" />
            
            <!-- 通知开关 -->
            <Switch IsToggled="{Binding IsNotificationsEnabledToggled}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

方案2:使用EventToCommandBehavior处理切换事件(需区分控件时)

如果需要在事件触发时执行额外逻辑(比如记录操作日志、触发异步任务),可以用MAUI Community Toolkit的EventToCommandBehavior,通过CommandParameter传递标识区分不同Switch。

XAML代码

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyProject.Views.SettingsPage"
             xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             xmlns:vm="clr-namespace:MyProject.ViewModels"
             x:DataType="vm:SettingsPageViewModel"
             BackgroundColor="{DynamicResource PageBackGround}">

    <ContentPage.Content>
        <StackLayout>
            <!-- 暗黑模式开关 -->
            <Switch IsToggled="{Binding IsDarkModeToggled}">
                <Switch.Behaviors>
                    <mct:EventToCommandBehavior
                        EventName="Toggled"
                        Command="{Binding SwitchToggledCommand}"
                        CommandParameter="DarkMode" />
                </Switch.Behaviors>
            </Switch>
            
            <!-- 通知开关 -->
            <Switch IsToggled="{Binding IsNotificationsEnabledToggled}">
                <Switch.Behaviors>
                    <mct:EventToCommandBehavior
                        EventName="Toggled"
                        Command="{Binding SwitchToggledCommand}"
                        CommandParameter="Notifications" />
                </Switch.Behaviors>
            </Switch>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

ViewModel代码

namespace MyProject.ViewModels
{
    public partial class SettingsPageViewModel : BaseViewModel
    {
        private bool _isDarkModeToggled;
        public bool IsDarkModeToggled
        {
            get => _isDarkModeToggled;
            set => SetProperty(ref _isDarkModeToggled, value);
        }

        private bool _isNotificationsEnabledToggled;
        public bool IsNotificationsEnabledToggled
        {
            get => _isNotificationsEnabledToggled;
            set => SetProperty(ref _isNotificationsEnabledToggled, value);
        }

        ILogger<SettingsPageViewModel> _logger;
        public SettingsPageViewModel(ILogger<SettingsPageViewModel> logger)
        {
            _logger = logger;
            IsDarkModeToggled = true;
        }

        [RelayCommand]
        public void SwitchToggled(string switchId)
        {
            bool currentState = switchId switch
            {
                "DarkMode" => IsDarkModeToggled,
                "Notifications" => IsNotificationsEnabledToggled,
                _ => false
            };

            _logger.LogInformation($"开关[{switchId}]状态变更为{(currentState ? "开启" : "关闭")}");
            
            // 根据开关ID执行对应逻辑
            switch(switchId)
            {
                case "DarkMode":
                    // 处理暗黑模式逻辑
                    break;
                case "Notifications":
                    // 处理通知逻辑
                    break;
            }
        }
    }       
}

注意事项

  1. 不要直接操作UI控件:如果需要修改Switch的颜色、样式等,应通过绑定ViewModel的属性实现,比如:

    <Switch IsToggled="{Binding IsDarkModeToggled}"
            Color="{Binding DarkModeSwitchColor}" />
    

    在ViewModel中添加DarkModeSwitchColor属性,根据状态返回对应的颜色值。

  2. 传递事件参数:如果需要获取ToggledEventArgs,可以设置PassEventArgsToCommand="True",但这种方式无法区分哪个Switch触发,建议结合CommandParameter一起使用。

  3. BaseViewModel的SetProperty:确保你的BaseViewModel实现了INotifyPropertyChanged,并提供SetProperty方法来触发属性变更通知,这是数据绑定生效的前提。

内容的提问来源于stack exchange,提问作者Andy Donegan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:25:01