約束どおり、例を示します。
シナリオ: 2 つの DataGrid があります。1 つの DataGrid には、会社と他のサイトが含まれています。
条件: 会社が選択されるたびに、選択されたサイトが関連する会社のサイトを反映するように変更されます。
実装: MVVM、SelectedCompany プロパティを変更すると、ViewModel のSelectedSiteプロパティが更新されます。
注: DataGrid スタイルを追加して、Lost-Focus 状態を表示できるようにしました。デフォルトでは、選択した行は Lost Focus では表示されません。
モデル:
会社
using System;
using System.ComponentModel;
namespace CascadingDataGrids
{
public class Company : INotifyPropertyChanged
{
private int _id;
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>
/// The id.
/// </value>
public int Id
{
get { return _id; }
set
{
if (value != _id)
{
_id = value;
NotifyPropertyChanged("Id");
}
}
}
private string _companyName;
/// <summary>
/// Gets or sets the name of the company.
/// </summary>
/// <value>
/// The name of the company.
/// </value>
public string CompanyName
{
get { return _companyName; }
set
{
{
if (value != _companyName)
{
_companyName = value;
NotifyPropertyChanged("CompanyName");
}
}
}
}
private int _siteId;
/// <summary>
/// Gets or sets the site id.
/// </summary>
/// <value>
/// The site id.
/// </value>
public int SiteId
{
get { return _siteId; }
set
{
if (value != _siteId)
{
_siteId = value;
NotifyPropertyChanged("SiteId");
}
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
}
サイト
using System;
using System.ComponentModel;
namespace CascadingDataGrids
{
public class Site : INotifyPropertyChanged
{
private int _id;
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>
/// The id.
/// </value>
public int Id
{
get { return _id; }
set
{
if (value != _id)
{
_id = value;
NotifyPropertyChanged("Id");
}
}
}
private string _siteName;
/// <summary>
/// Gets or sets the name of the site.
/// </summary>
/// <value>
/// The name of the site.
/// </value>
public string SiteName
{
get { return _siteName; }
set
{
{
if (value != _siteName)
{
_siteName = value;
NotifyPropertyChanged("SiteName");
}
}
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
}
ビューモデル:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
namespace CascadingDataGrids
{
public class DemoViewModel : INotifyPropertyChanged
{
#region Properties
private ObservableCollection<Company> _companies;
/// <summary>
/// Gets or sets the companies.
/// </summary>
/// <value>
/// The companies.
/// </value>
public ObservableCollection<Company> Companies
{
get { return _companies; }
set
{
if (value != _companies)
{
_companies = value;
NotifyPropertyChanged("Companies");
}
}
}
private Company _selectedCompany;
/// <summary>
/// Gets or sets the selected company.
/// </summary>
/// <value>
/// The selected company.
/// </value>
public Company SelectedCompany
{
get { return _selectedCompany; }
set
{
if (value != _selectedCompany)
{
_selectedCompany = value;
NotifyPropertyChanged("SelectedCompany");
// Set Site
var currentSite =
Sites.FirstOrDefault(x => x.Id == SelectedCompany.SiteId);
// Evaluate
if (currentSite != null)
{
SelectedSite = currentSite;
}
}
}
}
private ObservableCollection<Site> _sites;
/// <summary>
/// Gets or sets the sites.
/// </summary>
/// <value>
/// The sites.
/// </value>
public ObservableCollection<Site> Sites
{
get { return _sites; }
set
{
if (value != _sites)
{
_sites = value;
NotifyPropertyChanged("Sites");
}
}
}
private Site _selectedSite;
/// <summary>
/// Gets or sets the selected site.
/// </summary>
/// <value>
/// The selected site.
/// </value>
public Site SelectedSite
{
get { return _selectedSite; }
set
{
if (value != _selectedSite)
{
_selectedSite = value;
NotifyPropertyChanged("SelectedSite");
}
}
}
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="DemoViewModel"/> class.
/// </summary>
public DemoViewModel()
{
// New instances
Companies = new ObservableCollection<Company>();
Sites = new ObservableCollection<Site>();
// Build
BuildCompanies();
BuildSites();
}
#endregion
#region Members
/// <summary>
/// Builds the companies.
/// </summary>
private void BuildCompanies()
{
// Set companies
Companies = new ObservableCollection<Company>
{
new Company { Id = 1, CompanyName = "Microsoft", SiteId = 1 },
new Company { Id = 2, CompanyName = "Google", SiteId = 3 },
new Company { Id = 3, CompanyName = "Amazon", SiteId = 2 },
};
// Set selected to first value
SelectedCompany = Companies.FirstOrDefault();
}
/// <summary>
/// Builds the sites.
/// </summary>
private void BuildSites()
{
// Set sites
Sites = new ObservableCollection<Site>
{
new Site { Id = 1, SiteName = "Redmond, WA" },
new Site { Id = 2, SiteName = "Seattle, WA" },
new Site { Id = 3, SiteName = "Mountain View, CA" }
};
// Set selected to first value
SelectedSite = Sites.FirstOrDefault();
}
#endregion
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
}
表示: XAML
<Window x:Class="CascadingDataGrids.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Companies and Sites" Height="700" Width="500">
<Window.Resources>
<Style x:Key="Header" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Calibri" />
<Setter Property="FontSize" Value="20" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<!-- Datagrid -->
<Style TargetType="{x:Type DataGrid}">
<Setter Property="Background" Value="White" />
<Setter Property="CanUserAddRows" Value="False" />
<Setter Property="CanUserResizeRows" Value="False" />
<Setter Property="CanUserDeleteRows" Value="False" />
<Setter Property="SelectionMode" Value="Single" />
<Setter Property="SelectionUnit" Value="FullRow" />
<Setter Property="EnableRowVirtualization" Value="True" />
</Style>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Cursor" Value="Hand" />
<Style.Triggers>
<!-- Hover -->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1" Opacity="0.5">
<GradientStop Color="#dceef7" Offset="0" />
<GradientStop Color="#f2f9fc" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<!-- Selected -->
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1" Opacity="1">
<GradientStop Color="#333" Offset="0" />
<GradientStop Color="#333" Offset="0.01" />
<GradientStop Color="#e0e4e7" Offset="0.01" />
<GradientStop Color="#c2dbea" Offset="0.40" />
<GradientStop Color="#c2dbea" Offset="0.60" />
<GradientStop Color="#e0e4e7" Offset="0.99" />
<GradientStop Color="#333" Offset="0.99" />
<GradientStop Color="#333" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="240" />
<RowDefinition Height="40" />
<RowDefinition Height="24" />
<RowDefinition Height="240" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Style="{StaticResource Header}" Text="Companies" />
<DataGrid Grid.Row="1" Margin="0 12 0 0"
ItemsSource="{Binding Path=Companies}"
SelectedItem="{Binding Path=SelectedCompany, Mode=TwoWay}"
RowHeight="20"
IsReadOnly="True" />
<TextBlock Grid.Row="3" Style="{StaticResource Header}" Text="Sites" />
<DataGrid Grid.Row="4" Margin="0 12 0 0"
ItemsSource="{Binding Path=Sites}"
SelectedItem="{Binding Path=SelectedSite, Mode=TwoWay}"
RowHeight="20"
IsReadOnly="True" />
</Grid>
</Window>
表示: コード ビハインド
using System.Windows;
namespace CascadingDataGrids
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Members
private readonly DemoViewModel _vm;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="MainWindow"/> class.
/// </summary>
public MainWindow()
{
// Set viewmodel
_vm = new DemoViewModel();
// Set data context
this.DataContext = _vm;
// Initialize UI
InitializeComponent();
}
#endregion
}
}