MVVMでラジオボタンを実装する方法をサンプル付きで紹介します。それとなくバインドしてもうまくいかず、思ったより難しかったので自分用に記事にしました。似た機能のチェックボックスやコンボボックスなどと比べてやや難易度が高いです。
ラジオボタンについて
チェックボックスやコンボボックスとの使い分け
ラジオボタン、チェックボックス、コンボボックスのよくある共通の使い方として、
複数の選択肢を表示し、その中からユーザが選択できる
があります。
それぞれの使い分け(違い)としては以下の通りのように考えています。
・ラジオボタン ・・・複数の選択肢から1つ選ぶとき
・コンボボックス ・・・複数の選択肢から1つ選ぶ+画面上スペースを節約したいとき
・チェックボックス・・・複数の選択肢から複数選ぶとき
選択肢1つ選ぶ場合において、画面が狭い・視点移動が大きすぎる場合はコンボボックス、選択肢が常時表示されたほうが良い場合はラジオボタン、といったところですかね。
コンボボックスの記事(サンプルコードあり)はこちら。
実装における要点
後述のサンプルを作る過程で、以下が要点と感じたので記載。
- enum(列挙型)で選択肢を定義
- enumとBooleanを変換するコンバータの実装
- enumデータと<RadioButton/>側の”IsChecked(bool)”をバインドする
コンボボックスみたいな感じでバインドできればらくなのに。。。
サンプルコード(MVVM)
以下のようなサンプルを作成しました。
ラジオボタンの選択を切り替えると、TextBlockの表示が切り替わります。
MVVMプロジェクトの作成方法はこちらにまとまっています。
View
XAMLは以下の通り。
ViewModelに記述したコンバータ(EnumToBooleanConverter)を利用します。
<Window x:Class="RadioButtonSample.Views.MainWindow" 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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:RadioButtonSample.ViewModels" mc:Ignorable="d" Title="RadioButtonSample" Height="150" Width="150"> <!--コンバータを定義--> <Window.Resources> <ResourceDictionary> <local:EnumToBooleanConverter x:Key="EnumToBoolean" /> </ResourceDictionary> </Window.Resources> <Grid> <StackPanel Orientation="Vertical" > <!--ラジオボタン--> <StackPanel Orientation="Vertical" Margin="10"> <RadioButton Content="タイプ1" IsChecked="{Binding Path=sentakushi,Mode=TwoWay, Converter={StaticResource EnumToBoolean}, ConverterParameter=Type1, UpdateSourceTrigger=PropertyChanged}" /> <RadioButton Content="タイプ2" IsChecked="{Binding Path=sentakushi,Mode=TwoWay, Converter={StaticResource EnumToBoolean}, ConverterParameter=Type2, UpdateSourceTrigger=PropertyChanged}" /> <RadioButton Content="タイプ3" IsChecked="{Binding Path=sentakushi,Mode=TwoWay, Converter={StaticResource EnumToBoolean}, ConverterParameter=Type3, UpdateSourceTrigger=PropertyChanged}" /> </StackPanel> <!--表示用テキスト--> <TextBlock Text="{Binding selectedtxt}" Margin="20" Background="AliceBlue"/> </StackPanel> </Grid> </Window>
コードビハインドは以下の通り(いつもの)。
using RadioButtonSample.ViewModels; using System.Windows; namespace RadioButtonSample.Views { public partial class MainWindow : Window { MainViewModel vm = new MainViewModel(); public MainWindow() { InitializeComponent(); this.DataContext = vm; } } }
ViewModel
ラジオボタンの選択肢、コンバータを記載します。
using System; using System.ComponentModel; using System.Windows; using System.Windows.Data; using System.Globalization; namespace RadioButtonSample.ViewModels { internal class MainViewModel : INotifyPropertyChanged { public MainViewModel() { } //選択肢の変数 private Choices _sentakushi; public Choices sentakushi { get { return _sentakushi; } set { _sentakushi = value; NotifyPropertyChanged("sentakushi"); //表示用テキストの更新 selectedtxt=value.ToString(); } } //表示用テキスト private string _selectedtxt = ""; public string selectedtxt { get { return _selectedtxt; } set { _selectedtxt = value; NotifyPropertyChanged("selectedtxt"); } } //変数の更新をViewへ通知する用 public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } } //ラジオボタンの選択肢 public enum Choices { Type1, Type2, Type3 }; //列挙型をBooleanに変換するコンバータ public class EnumToBooleanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var parameterString = parameter as string; if (null == parameterString) return DependencyProperty.UnsetValue; if (!Enum.IsDefined(value.GetType(), value)) return DependencyProperty.UnsetValue; var parameterValue = Enum.Parse(value.GetType(), parameterString); return parameterValue.Equals(value); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var parameterString = parameter as string; if (null == parameterString) return DependencyProperty.UnsetValue; if (true.Equals(value)) return Enum.Parse(targetType, parameterString); else return DependencyProperty.UnsetValue; } } }
Modelは実装なし。
参考にさせていただいたサイト(外部)様はこちら。
コメント