XAMLを使わないWPF入門28「ON/OFFを切り替えるトグルボタン」

コンピュータ

MVVMぽく切り替えボタンを作成してみました。

・起動時はボタンの文字は「ON」
image

・ボタンをクリックすると「OFF」に切り替わる
image

ファイル名:NoXaml28Button.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

ファイル名:App.cs


using System;
using System.Windows;

namespace NoXaml28Button;

public class App : Application
{
    [STAThread]
    public static void Main(string[] args)
    {
        var app = new App();
        app.Run();
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var viewModel = new MainWindowViewModel();


        var win = new MainWindow
        {
            DataContext = viewModel,
        };
        win.Show();
    }
}

ファイル名:AssemblyInfo.cs


using System.Windows;

[assembly:ThemeInfo(
    ResourceDictionaryLocation.None,            //where theme specific resource dictionaries are located
                                                //(used if a resource is not found in the page,
                                                // or application resource dictionaries)
    ResourceDictionaryLocation.SourceAssembly   //where the generic resource dictionary is located
                                                //(used if a resource is not found in the page,
                                                // app, or any theme specific resource dictionaries)
)]

ファイル名:Helper\RelayCommand.cs


using System.Windows.Input;

public class RelayCommand : ICommand
{
    private readonly Action<object?> _execute;
    private readonly Func<object?, bool>? _canExecute;

    public RelayCommand(Action<object?> execute, Func<object?, bool>? canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object? parameter) => _canExecute?.Invoke(parameter) ?? true;

    public void Execute(object? parameter) => _execute(parameter);

    public event EventHandler? CanExecuteChanged;
    public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

ファイル名:View\MainWindow.cs


using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;

namespace NoXaml28Button;

public class MainWindow : Window
{
    public MainWindow()
    {
        this.Title = "NoXAML Button Sample";
        this.Width = 400;
        this.Height = 300;

        // UIの構築
        var stackPanel = new StackPanel
        {
            VerticalAlignment = VerticalAlignment.Center,
            HorizontalAlignment = HorizontalAlignment.Center
        };
        var toggleButton = new ToggleButton
        {
            Width = 150,
            Height = 50,
            Margin = new Thickness(20)
        };
        stackPanel.Children.Add(toggleButton);

        // コマンドバインディング
        var isCheckedBinding = new Binding("IsOn") { Mode = BindingMode.TwoWay };
        BindingOperations.SetBinding(toggleButton, ToggleButton.IsCheckedProperty, isCheckedBinding);

        // コンテンツバインディング
        var switchDisplayValueBinding = new Binding("SwitchDisplayValue");
        BindingOperations.SetBinding(toggleButton, Button.ContentProperty, switchDisplayValueBinding);

        this.Content = stackPanel;
    }
}

ファイル名:ViewModel\MainWindowViewModel.cs


using System.Windows;
using System.Windows.Input;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Dynamic;

namespace NoXaml28Button;

public class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string? name = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    public ICommand ClickCommand { get; }

    private bool _isOn = true;
    public bool IsOn
    {
        get => _isOn;
        set
        {
            if (_isOn == value) return;
            _isOn = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(SwitchDisplayValue)); // SwitchDisplayValueにも変更通知を送る。
        }
    }

    /*
    private string _switchDisplayValue = "ON";
    public string SwitchDisplayValue
    {
        get => _switchDisplayValue;
        set
        {
            if (_switchDisplayValue == value) return;
            _switchDisplayValue = value;
            OnPropertyChanged();
        }
    }
    */
    public string SwitchDisplayValue => IsOn ? "ON" : "OFF";

    public MainWindowViewModel()
    {
        ClickCommand = new RelayCommand(_ =>
        {
            //MessageBox.Show("ボタンがクリックされました!");
            this.IsOn = !this.IsOn;
        });

        /*
        this.PropertyChanged += (s, e) =>
        {
            if (e.PropertyName == nameof(this.SwitchFlag))
            {
                if (this.SwitchFlag == true)
                {
                    this.SwitchDisplayValue = "ON";
                }
                else
                {
                    this.SwitchDisplayValue = "OFF";
                }
            }
        };
        */

    }
}

コメント