MVVMやMEFなどをベースにしたWAF(WPF Application Framework)を使ってアプリケーションを開発しています。
私は現在、以下のような構造のドメインオブジェクトをいくつか持っています(簡潔にするために短縮されています):
public class MyBaseClass : INotifyPropertyChanged
{
private DateTime? _firstDateTime;
protected DateTime? firstDateTime
{
get { return _firstDateTime; }
set
{
_firstDateTime = value;
OnPropertyChanged(new PropertyChangedEventArgs("FirstDateTime"));
}
private DateTime? _secondDateTime;
protected DateTime? secondDateTime
{
get { return _secondDateTime; }
set
{
_secondDateTime = value;
OnPropertyChanged(new PropertyChangedEventArgs("SecondDateTime"));
}
public DateTime? FirstDateTime
{
get { return firstDateTime; }
set { firstDateTime = value; }
}
public DateTime? SecondDateTime
{
get { return secondDateTime; }
set { secondDateTime = value; }
}
}
public class MyBaseCollectionClass : INotifyPropertyChanged
{
private ObservableCollection<MyBaseClass> _baseClassObjectCollection;
protected ObservableCollection<MyBaseClass> baseClassObjectCollection
{
get { return _baseClassObjectCollection; }
set
{
_baseClassObjectCollection = value;
OnPropertyChanged(new PropertyChangedEventArgs("BaseClassObjectCollection"));
}
}
public ObservableCollection<MyBaseClass> BaseClassObjectCollection
{
get { return baseClassObjectCollection; }
set { baseClassObjectCollection = value; }
}
}
次に、ApplicationControllerに、次のようなビューモデルにObservableCollectionをロードするメソッドがあります。
for (int i = 0; i <= 9; i++)
{
detailsViewModel.MyBaseClassObjects.Add( new MyBaseClass()
{
FirstDateTime = Convert.ToDateTime("05/2" + i + "/2012 09:00:00 AM"),
SecondDateTime = Convert.ToDateTime("05/2" + i + "/2012 04:30:00 PM")
});
}
そして、大きなコレクションを日付ごとに小さなグループ化されたコレクションにグループ化する別の方法:
detailsViewModel.MyBaseClassObjects
.GroupBy(baseObject => ((DateTime)baseObject.FirstDateTime).Date)
.Select(group => group.ToList())
.ToList()
.ForEach(list => detailsViewModel.BaseObjectCollections
.Add(
new MyBaseCollectionClass()
{ BaseClassObjectCollection = new ObservableCollection<MyBaseClass>(list)}
)
);
次に、ビューのXAMLで、次のようにバインドされたItemsControlがあります。
<ItemsControl ItemsSource="{Binding BaseObjectCollections}" ItemTemplate="{StaticResource ItemsTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
ビューのResourceDictionaryで、そのように宣言されたDataTemplateがあります(わかりやすくするために一部の項目は省略されています)。
<DataTemplate x:Key="ItemsTemplate">
<Grid DataContext="{Binding MyBaseClassObjects}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid Grid.Row="1"
Background="Transparent"
Style="{DynamicResource DataGridStyle}"
AlternatingRowBackground="Gainsboro"
AlternationCount="2"
AutoGenerateColumns="False"
HeadersVisibility="None"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}, Path=DataContext}">
<DataGrid.Columns>
<DataGridTextColumn Width=".25*">
<DataGridTextColumn.Binding>
<MultiBinding Converter="{x:Static myConvNS:MultiValueTESTCONVERTER.Retrieve}">
<Binding Path="FirstDateTime"/>
<Binding Path="SecondDateTime"/>
</MultiBinding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</DataTemplate>
注:上記のDataTemplateには現在マルチバインディングがあるため、コンバーターに渡されている値を確認できます。目的の効果(以下で説明)を達成できないことはわかっていますが、バインディングをステップスルーして、コンバーターが何を受信しているかを確認できるようにしたかったのです。現時点ではこれ以上のことはありません。最終的に私が達成しようとしているのは(可能であれば)、FirstDateTimeとSecondDateTimeの値が同じ列に交互に表示されるようにDatagridをバインドできるようにすることです。視覚的な補助については、以下の画像を参照してください。
私の最初の考えは、単一のDateTimeプロパティを公開し、ベースオブジェクト(2つのDateTimeプロパティを持つ)をこのジェネリックオブジェクトのインスタンスに分解し、それらのジェネリックオブジェクトのコレクションにバインドする他のジェネリックオブジェクトを用意することでした。しかし、私はこの考えが好きではありません。ベースオブジェクトのいずれかのDateTimeプロパティに変更が発生した場合、それについて知る必要があります。このオブジェクトを2つの汎用オブジェクトに分割すると、通知を正しく送受信できなくなるのではないかと心配しています。
誰か提案や考えがありますか?