WPFプラットフォームで使える表計算・グリッドコントロール「SPREAD for WPF(スプレッド)」は、MVVM(Model View View-Model)パターンに対応したプログラミングが可能です。
その内容を解説した記事がCodeZineに掲載されています。
初期バージョンからMVVMに対応していますが、SPREAD for WPF 2.0Jではデータバインド機能を強化しました。そのためSPREADコントロールだけでなくセルにバインディングが可能です。この記事ではセルバインディングについて解説します。
セルのバインディング
セルのスタイルをXAMLで設定するにはCellPresenter
クラスを使用します。
SPREAD for WPF 2.0J以降では、セルの値を表すValue
プロパティを、WPFのバインディング機能の前提である依存関係プロパティとして提供しています。
Valueプロパティを依存関係プロパティとして提供することで、セルの値に応じてセルのスタイルを変更できるようになります。その処理はXAMLで記述するため、コードビハインドの記述を削減できます。
MVVMの実装では、コードビハインドに出来るだけ処理を記述せず、ビューとビューモデルがWPFのバインディングで対話することを要望されるケースは少なくありません。そのためセルにもバインディング機能を用意しました。その機能を、具体的に利用した例で解説します。
コンボボックスの値に応じてセルの外観を変更
以下のサンプルでは、ウィンドウにコンボボックスとSPREADが配置されています。
SPREADは、お客様から受けた問い合わせを一覧で表示し、コンボボックスには、期間を表す値が設定されています。コンボボックスで選択された値に応じて、該当するSPREADのセルを、文字を赤色に変更して強調表示します。
このアプリケーションを構成するMVVM(モデル・ビュー・ビューモデル)の各要素は以下のとおりです。
記載しているコードの主要部分を抽出しています。本記事の最後にサンプルプロジェクトのダウンロードリンクがあります。
モデル(Model)
モデルは、問合せを表すCustomerRequestクラスです。
Visual Basic
Public Class CustomerRequest Public Property ID() As String Public Property Title() As String Public Property OpenDate() As DateTime Public Property Note() As String End Class
C#
public class CustomerRequest { public string ID { get; set; } public string Title { get; set; } public DateTime OpenDate { get; set; } public string Note { get; set; } }
ビューモデル(View-Model)
ビューモデルのCustomerRequestViewModelクラスは、次の2つのプロパティをもちます。
- 問合せのコレクション(
CustomerRequests
プロパティ) - 強調表示する期間(
FocusDays
プロパティ)
Visual Basic
Public Class CustomerRequestViewModel Implements INotifyPropertyChanged Private _requests As ObservableCollection(Of CustomerRequest) Public Sub New() _requests = (New CustomerRequestCollection()).GetCustomerRequests() End Sub Public Property CustomerRequests() As ObservableCollection(Of CustomerRequest) Get Return _requests End Get Set If Not _requests.Equals(Value) Then _requests = Value NotifyPropertyChanged("CustomerRequests") End If End Set End Property Private _days As Integer Public Property FocusDays() As Integer Get Return _days End Get Set If _days <> Value Then _days = Value NotifyPropertyChanged("FocusDays") End If End Set End Property Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged Private Sub NotifyPropertyChanged(propertyName As [String]) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) End Sub End Class
C#
public class CustomerRequestViewModel : INotifyPropertyChanged { // 問合せのコレクション private ObservableCollection<CustomerRequest> _requests; public CustomerRequestViewModel() { _requests = (new CustomerRequestCollection()).GetCustomerRequests(); } public ObservableCollection<CustomerRequest> CustomerRequests { get { return _requests; } set { if (_requests != value) { _requests = value; NotifyPropertyChanged("CustomerRequests"); } } } // 強調する期間 private int _days; public int FocusDays { get { return _days; } set { if (_days != value) { _days = value; NotifyPropertyChanged("FocusDays"); } } } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
また、ビューとのバインディングで使用するコンバーターを作成します。
コンバーターは、SPREADのセルと、強調表示する期間の2つの値を扱えるよう、IMultiValueConverter
インタフェースを実装します。
Visual Basic
Public Class FocusDaysConverter Implements IMultiValueConverter Public Function Convert(values As Object(), targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert Dim result As Boolean = False If TypeOf values(0) Is DateTime Then Dim [date] As DateTime = DirectCast(values(0), DateTime) If values(1) IsNot Nothing Then Dim days As Integer = Integer.Parse(values(1).ToString()) result = DateTime.Today.Subtract([date]).Days < days End If End If Return result End Function Public Function ConvertBack(value As Object, targetTypes As Type(), parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack Throw New NotImplementedException() End Function End Class
C#
public class FocusDaysConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { bool result = false; if (values[0] is DateTime) { // SPREADセルの日付値 DateTime date = (DateTime)values[0]; if (values[1] != null) { // 強調する期間に該当するか int days = int.Parse(values[1].ToString()); result = DateTime.Today.Subtract(date).Days < days; } } return result; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
ビュー(View)
ビューは、WPFのウィンドウを表すMainWindow.xamlと、そのコードビハインド(MainWindow.xaml.csまたはMainWindow.xaml.vb)です。
ウィンドウのDataContext
プロパティにビューモデルを設定します。
これで、ウィンドウのコンボボックスとSPREADに、ビューモデルのプロパティをバインドできます。
<Window.DataContext> <!--ビューモデルを設定--> <local:CustomerRequestViewModel/> </Window.DataContext>
コンボボックス
コンボボックスで選択された値が、強調表示する期間です。
これを実現するために、コンボボックスのSelectedValue
プロパティを、ビューモデルのFocusDays
プロパティにバインドします。
<!--選択された値をビューモデルのFocusDaysプロパティにバインド--> <ComboBox SelectedValue="{Binding FocusDays, Mode=TwoWay}" …省略…>
SPREAD
SPREADには問い合わせのコレクションを表示します。
これを実現するために、SPREADのItemsSource
プロパティを、ビューモデルのCustomerRequests
プロパティにバインドします。
また、強調表示する期間に該当するセルの文字を赤色に変更します。
これを実現するために、SPREADのCellStyle
プロパティにDataTrigger
を設定します。MultiBinding
を使用して、セルの値と、ビューモデルのFocusDays
プロパティをバインドします。
<sg:GcSpreadGrid ItemsSource="{Binding CustomerRequests}" …省略…> <!--セルのバインディングを設定--> <sg:GcSpreadGrid.CellStyle> <Style TargetType="{x:Type sg:CellPresenter}"> <Style.Triggers> <DataTrigger Value="True"> <DataTrigger.Binding> <MultiBinding Converter="{StaticResource FocusDaysConverter}"> <!--セルの値--> <Binding RelativeSource="{RelativeSource Self}" Path="Value"/> <!--ビューモデルのFocusDaysプロパティ--> <Binding Path="FocusDays"/> </MultiBinding> </DataTrigger.Binding> <Setter Property="FontWeight" Value="Bold"/> <Setter Property="FontSize" Value="13"/> <Setter Property="Foreground" Value="Red"/> </DataTrigger> </Style.Triggers> </Style> </sg:GcSpreadGrid.CellStyle> <sg:GcSpreadGrid.Columns …以降、省略… </sg:GcSpreadGrid>
実行
アプリケーションを実行すると、コンボボックスの値に応じて、対象のセルの文字が赤色に変化します。
サンプルプロジェクト
本記事のサンプルプロジェクトは以下からダウンロードできます。Zip形式(27KB)
業務アプリケーションのアーキテクチャ
実践的な業務アプリケーションのアーキテクチャを解説した記事がCodeZineに記載されています。
実際の開発現場で実践的なMVVMパターンの開発の解説です。こちらの記事中のサンプルでSPREAD for WPFが利用されています。
SPREAD for WPFの機能を体感
.NET FrameworkのClick Once機能を利用したデモを公開しています。
Windows PCにWebサイトからインストールして、SPREAD for WPFの機能を実際にお試しいただけます。