メートル法 と ヤード・ポンド法 の値変換プログラムを、WPF の データバインディングを使って作成します。
ここに記載のプログラムは、全て「日経ソフトウェア 2015年9月号」中の「基礎からわかる C# デスクトップアプリ開発 第3回」からの引用です。
最初にアプリ画面を作成します。
こんな感じです。画面要素だけで動作にかかわる実装は一切ありません。
[プログラムソース "MainWindow.xaml"]
<Window x:Class="MeterYardConverter.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:MeterYardConverter" mc:Ignorable="d" Title="Meter/Yard Converter" FontSize="26.667" FontFamily="Segoe UI Light" SizeToContent="WidthAndHeight" ResizeMode="NoResize"> <StackPanel Margin="4"> <StackPanel Orientation="Horizontal"> <TextBox TextWrapping="Wrap" Text="TextBox" Width="100" Margin="4"/> <ComboBox Width="80" Margin="4"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <Button Content="▲" Width="40" Margin="4"/> <Button Content="▼" Width="40" Margin="4"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBox TextWrapping="Wrap" Text="TextBox" Width="100" Margin="4"/> <ComboBox Width="80" Margin="4"/> </StackPanel> </StackPanel> </Window>
データバインディングを実装するために、 INotifyPropertyChanged を継承した ViewModel を作成します。
注意:
・[CallerMemberName] は .NET4.5 以降で使用できます。
using System.ComponentModel; // INotifyPropertyChanged
using System.Runtime.CompilerServices; // CallerMemberName
namespace MeterYardConverter
{
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
データバインディングを実装するために、 ICommand を継承した DelegateCommand を作成します。
[プログラムソース "DelegateCommand.cs"]
using System;
using System.Windows.Input; // ICommand
namespace MeterYardConverter
{
public class DelegateCommand : ICommand
{
private readonly Action execute;
private readonly Func<bool> canExecute;
public DelegateCommand(Action execute)
: this(execute, () => true)
{ }
public DelegateCommand(Action execute, Func<bool> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
public void Execute(object parameter)
{
this.execute();
}
public bool CanExecute(object parameter)
{
return this.canExecute();
}
// 以下は今回のプログラムでは使用しませんが、参考記載。
public event EventHandler CanExecuteChanged;
public void NotifyCanExcuteChanged()
{
if ( CanExecuteChanged != null )
{
CanExecuteChanged( this, EventArgs.Empty);
}
}
}
}
モデルの実装を行います。
各単位の宣言と、単位間の変換を行うめっそっどの実装を行います。
using System.Collections.Generic; namespace MeterYardConverter { public class DistanceUnit { public string Name { get; set; } public double Coefficient { get; set; } public override string ToString() { return this.Name; } } /// <summary> /// メートル単位を表すクラス /// </summary> public class MetricUnit : DistanceUnit { private static List<MetricUnit> _units = new List<MetricUnit> { new MetricUnit {Name="mm", Coefficient=1, }, new MetricUnit {Name="cm", Coefficient=10, }, new MetricUnit {Name="m", Coefficient=10*100, }, new MetricUnit {Name="km", Coefficient=10*100*1000, }, }; public static ICollection<MetricUnit> Units { get { return _units; } } public double FromImperialUnit(ImperialUnit unit, double value) { return (value * unit.Coefficient) * 25.4 / this.Coefficient; } } /// <summary> /// ヤード単位を表すクラス /// </summary> public class ImperialUnit : DistanceUnit { private static List<ImperialUnit> _units = new List<ImperialUnit> { new ImperialUnit {Name="in", Coefficient=1, }, // インチ new ImperialUnit {Name="ft", Coefficient=12, }, // フィート new ImperialUnit {Name="yd", Coefficient=12*3, }, // ヤード new ImperialUnit {Name="ml", Coefficient=12*3*1760, }, // マイル }; public static ICollection<ImperialUnit> Units { get { return _units; } } public double FromMetricUnit(MetricUnit unit, double value) { return (value * unit.Coefficient) / 25.4 / this.Coefficient; } } }
ビューモデルを実装します。
[プログラムソース "MainWindowViewModel.cs"]using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; // ICommand namespace MeterYardConverter { class MainWindowVIewModel : ViewModel { // 上のTextBoxで入力されている値 private double _metricValue; // 下のTextBoxで入力されている値 private double _imperialValue; // ▲ボタンで呼ばれるコマンド public ICommand ImperialUnitToMetricUnit { get; private set; } // ▼ボタンで呼ばれるコマンド public ICommand MetricUnitToImperialUnit { get; private set; } // 上のComboBoxで選択されている単位 public MetricUnit CurrentMetricUnit { get; private set; } // 下のComboBoxで選択されている単位 public ImperialUnit CurrentImperialUnit { get; private set; } public double MetricValue { get { return this._metricValue; } set { this._metricValue = value; this.OnPropertyChanged(); } } public double ImperialValue { get { return this._imperialValue; } set { this._imperialValue = value; this.OnPropertyChanged(); } } public MainWindowVIewModel() { // CurrnetMetricUnit の初期化 this.CurrentMetricUnit = MetricUnit.Units.First(); // CurrentImperialUnit の初期化 this.CurrentImperialUnit = ImperialUnit.Units.First(); // ICommand MetricUnitToImperialUnit の初期化 this.MetricUnitToImperialUnit = new DelegateCommand(() => { this.ImperialValue = this.CurrentImperialUnit.FromMetricUnit(this.CurrentMetricUnit, this.MetricValue); }); // ICommand ImperialUnitToMetricUnit の初期化 this.ImperialUnitToMetricUnit = new DelegateCommand(()=> { this.MetricValue = this.CurrentMetricUnit.FromImperialUnit(this.CurrentImperialUnit, this.ImperialValue); }); } } }
ここまでに作成してきたモデルをビューに対してバインディングします。
下のソースを見てもらうとわかる通り、簡単ですね。
<Window x:Class="MeterYardConverter.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:MeterYardConverter" mc:Ignorable="d" Title="Meter/Yard Converter" FontSize="26.667" FontFamily="Segoe UI Light" SizeToContent="WidthAndHeight" ResizeMode="NoResize"> <Window.DataContext> <local:MainWindowVIewModel/> </Window.DataContext> <StackPanel Margin="4"> <StackPanel Orientation="Horizontal"> <TextBox TextWrapping="Wrap" Text="{Binding MetricValue, StringFormat=\{0:N3\}}" Width="100" Margin="4"/> <ComboBox Width="80" Margin="4" ItemsSource="{Binding Source={x:Static local:MetricUnit.Units}}" SelectedItem="{Binding CurrentMetricUnit}"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <Button Content="▲" Width="40" Margin="4" Command="{Binding ImperialUnitToMetricUnit, Mode=OneWay}"/> <Button Content="▼" Width="40" Margin="4" Command="{Binding MetricUnitToImperialUnit, Mode=OneWay}"/> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBox TextWrapping="Wrap" Text="{Binding ImperialValue, StringFormat=\{0:N3\}}" Width="100" Margin="4"/> <ComboBox Width="80" Margin="4" ItemsSource="{Binding Source={x:Static local:ImperialUnit.Units}}" SelectedItem="{Binding CurrentImperialUnit}"/> </StackPanel> </StackPanel> </Window>
最終的に完成したアプリケーションは以下の通りです。
サンプルプログラム ダウンロード
本ページの情報は、特記無い限り下記 MIT ライセンスで提供されます。
2023-04-14 | - | ページデザイン更新 |
2015-08-25 | - | 新規作成 |