既にデータ バインディングを使用して DataGrid コントロールのセルにデータを入力しているため、UI コードがバインドされているデータの構造 (DataContext がバインドされているオブジェクト) をシャッフルすることで、目的を達成できるはずです。行きます。
簡単で簡単な例をまとめました。クラス MyViewModel を「バインディング ターゲット」として作成し、クラス MyView をビュー/xaml として作成しました。まず、上記のコードと同様に、MyView には DataGrid があります。また、同じユーザー コントロールの DataGrid の下にいくつかのテキスト ボックスを追加しました。2 つは、選択したアイテムの名前フィールドとジョブ フィールドです。他の 2 つは、ユーザーの選択に基づいて入力する他のフィールドであると想定されています。たとえば、ユーザーが行を選択したときにデータベースから検索する追加データである可能性があります。MyView.xaml は次のとおりです。
<UserControl x:Class="WpfApplication1.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Items}"
IsReadOnly="True" SelectedItem="{Binding SelectedItem}"
SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Job" Binding="{Binding Job}"/>
</DataGrid.Columns>
</DataGrid>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<TextBox Width="100" Text="{Binding SelectedItem.Name, Mode=OneWay}" Margin="2"/>
<TextBox Width="100" Text="{Binding SelectedItem.Job, Mode=OneWay}" Margin="2"/>
<TextBox Width="100" Text="{Binding ExtraStuff.ExtraIntegerField, Mode=OneWay}" Margin="2"/>
<TextBox Width="100" Text="{Binding ExtraStuff.ExtraDoubleField, Mode=OneWay}" Margin="2"/>
</StackPanel>
</Grid>
ここで、DataGrid のバインディングのために、ItemsSource をコントロールの DataContext の特定のコレクションにバインドします。したがって、ここでは、DataContext はコレクション自体ではなく、行のアイテムとその他の情報の両方を含むオブジェクトです。また、パブリックなゲッターとセッターを持つ SelectedItem というプロパティに SelectedItem をバインドします。次に、MyView の DataContext が MyViewModel のインスタンスに設定されます。MyViewModel.cs は次のとおりです。
public sealed class MyViewModel : INotifyPropertyChanged
{
private readonly ObservableCollection<LightItem> _items = new ObservableCollection<LightItem>();
private LightItem _selectedItem;
private ExtraInformation _extraStuff;
public MyViewModel()
{
this._items.Add(new LightItem("Tim", "Dish Washer"));
this._items.Add(new LightItem("Bob", "Window Washer"));
this._items.Add(new LightItem("Jill", "Widget Washer"));
}
public event PropertyChangedEventHandler PropertyChanged;
public ExtraInformation ExtraStuff
{
get { return this._extraStuff; }
private set
{
this._extraStuff = value;
this.OnPropertyChanged("ExtraStuff");
}
}
public ReadOnlyObservableCollection<LightItem> Items { get { return new ReadOnlyObservableCollection<LightItem>(this._items); } }
public LightItem SelectedItem
{
get { return this._selectedItem; }
set
{
this._selectedItem = value;
this.OnPropertyChanged("SelectedItem");
this.ExtraStuff = new ExtraInformation(value);
}
}
private void OnPropertyChanged(string name)
{
if (null != this.PropertyChanged)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
public sealed class ExtraInformation
{
private readonly double _extraDoubleField;
private readonly int _extraIntegerField;
public ExtraInformation(LightItem light)
{
// you could get more info for your record from the db
// but here we just get some random numbers
var rnd = new Random();
this._extraDoubleField = rnd.NextDouble();
this._extraIntegerField = rnd.Next();
}
public double ExtraDoubleField { get { return this._extraDoubleField; } }
public double ExtraIntegerField { get { return this._extraIntegerField; } }
}
public sealed class LightItem
{
private readonly string _job;
private readonly string _name;
public LightItem(string name, string job)
{
this._name = name;
this._job = job;
}
public string Job { get { return this._job; } }
public string Name { get { return this._name; } }
}
}
ここで、プロパティ SelectedItem は、DataGrid の SelectedItem 依存関係プロパティにバインドしたものと同じです。そのタイプは、DataGrid の ItemsSource にバインドされている、私の Items コレクションにあるアイテムと同じタイプです。これで、SelectedItem のセッターが呼び出されたときに、それを更新して PropertyChanged イベントを発生させるだけではありません。また、新しい ExtraInformation オブジェクトを作成し、ExtrStuff に割り当てます。MyView.xaml をもう一度見ると、下部にある 2 つのテキスト ボックスの TextProperty が、このオブジェクトの integer フィールドと double フィールドにバインドされていることがわかります。ユーザーがこれらの項目のいずれかを選択するたびに、新しい乱数のセットが表示されます。
選択した項目に関する情報をデータベースから検索するまでは、これで終わりではありませんが、WPF データ バインディングを使用してこれをきれいに行う方法について正しい方向に導くことができれば幸いです。テキスト フィールドがどのウィンドウにあるかは問題ではありません。ほとんどの場合、両方のウィンドウの DataContext を同じ基になる MyViewModel にできるはずです。それがこのアプローチの素晴らしいところです。MyViewModel クラスは、選択したアイテムに関してデータベースに保存されている情報を検索する方法をカプセル化します。MyView は、バインドされているデータの一部が更新されたことを確認し、ユーザーが DataGrid 内の別の項目をクリックしたことを MyViewModel に知らせます。実際には、データがどのように見えるかをバインディング ターゲットで論理的に構造化します。次に、バインディングを使用して「ラッチオン」する方法をビュー部分に指示するだけです。また、さまざまなビューがさまざまな方法で「ラッチオン」できることも意味します。おそらく、Window1 には項目にバインドされた DataGrid があり、Window2 には SelectedItem と ExtraStuff の両方の情報にバインドされたテキスト フィールドがあり、Window3 には SelectedItem に関連付けられた画像が表示されているとします。各ウィンドウ/ビューは、バインディング ターゲット (ここでは MyViewModel インスタンス) 内のデータの異なる視覚的表現です。
このアイデアを示す簡単な図を次に示します。