WPF > 実装: DataGridを持つウィンドウ + ComboBoxを持つウィンドウ > データ同期

```txt:動作環境
Windows 8.1 Pro (64bit)
Microsoft Visual Studio 2017 Community
```

### 概要

http://qiita.com/7of9/items/9067fe160aa110f7b838
の続き。

- MainWindow: DataGridを持つウィンドウ
- ItemWindow: ComboBoxを持つウィンドウ

MainWindow上で項目を追加した時にItemWindowのComboBox項目に表示されるように実装した。

MVVM形式にしている（が理解不足で間違いがあるかも)。

### ファイル構成

- ItemWindow.xaml
- ItemWindow.xaml.cs : コードビハインド
- ItemWindowViewModel.cs : ViewModel
- MainWindow.xaml
- MainWindow.xaml.cs : コードビハインド
- MainWindowViewModel.cs : ViewModel
- SampleSingleton.cs : データ共有Singleton用
    - @calmbooks さんのコードを参考にしました 
- TestItem.cs : データの項目定義
- ViewModelBase.cs
    - @hugo-sb さんのコードを使わせていただいています。
    
### code

```ItemWindow.xaml
<Window x:Class="_170702_t1115_singleton_ObsCol.ItemWindow"
        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:_170702_t1115_singleton_ObsCol"
        mc:Ignorable="d"
        Title="ItemWindow" Height="300" Width="300" Closing="Window_Closing">
    <Window.DataContext>
        <local:ItemWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <ComboBox x:Name="uxItem" Height="30"
                  ItemsSource="{Binding myList}"
                  DisplayMemberPath="Name"/>
    </Grid>
</Window>
```

```ItemWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace _170702_t1115_singleton_ObsCol
{
    /// <summary>
    /// ItemWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class ItemWindow : Window
    {
        public ItemWindow()
        {
            InitializeComponent();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = true;
            this.Visibility = Visibility.Hidden;
        }
    }
}
```

```ItemWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//
using System.Collections.ObjectModel;

namespace _170702_t1115_singleton_ObsCol
{
    class ItemWindowViewModel : ViewModelBase
    {
        // コンストラクタ
        public ItemWindowViewModel()
        {
            myList = SampleSingleton.Instance;
        }

        public ObservableCollection<TestItem> myList { get; set; }
    }
}
```

```MainWindow.xaml
<Window x:Class="_170702_t1115_singleton_ObsCol.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:_170702_t1115_singleton_ObsCol"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button Content="Update" x:Name="uxUpdate" Width="100"
                        Command="{Binding UpdateCommand}"/>
                <Button Content="Open" x:Name="uxOpen" Width="100"
                        Command="{Binding OpenCommand}"/>
            </StackPanel>
            <DataGrid x:Name="dataGrid1" ItemsSource="{Binding myItem}"/>
        </StackPanel>
    </Grid>
</Window>
```

```MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace _170702_t1115_singleton_ObsCol
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}
```

```MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Windows;
using System.Data;
using System.Data.SqlClient;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace _170702_t1115_singleton_ObsCol
{
    class MainWindowViewModel : ViewModelBase
    {
        private ItemWindow itmWin = null;

        // コンストラクタ
        public MainWindowViewModel()
        {
            UpdateCommand = CreateCommand(param => MyUpdateCommand());
            OpenCommand = CreateCommand(param => MyOpenCommand());
            //
            myItem = SampleSingleton.Instance;
            myItem.Add(new TestItem { Id = 0, Name = "7of9", Age = 30, Gender = "Female" });

            var data2 = SampleSingleton.Instance;
            data2.Add(new TestItem { Id = 1, Name = "Janeway", Age = 50, Gender = "Female" });
        }

        public ObservableCollection<TestItem> myItem { get; set; }

        public ICommand UpdateCommand { get; private set; }
        public ICommand OpenCommand { get; private set; }

        public void MyUpdateCommand()
        {
            myItem.Add(new TestItem { Id = 2, Name = "Borg", Age = 45, Gender = "Male" });
        }

        public void MyOpenCommand()
        {
            if (itmWin == null)
            {
                itmWin = new ItemWindow();
            }
            itmWin.Show();
        }
    }
}
```

```SampleSingleton.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//
using System.Collections.ObjectModel;

namespace _170702_t1115_singleton_ObsCol
{
    class SampleSingleton
    {
        private static ObservableCollection<TestItem> instance;

        private SampleSingleton()
        {
        }

        public static ObservableCollection<TestItem> Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new ObservableCollection<TestItem>();
                }
                return instance;
            }
        }
    }
}
```

```TestItem.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _170702_t1115_singleton_ObsCol
{
    class TestItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Gender { get; set; }
    }
}
```

### 実行

初期状態
![2017-07-02_13h40_36.png](https://qiita-image-store.s3.amazonaws.com/0/32870/53c3a07f-fc4a-6a86-ca58-99b93f64ba78.png)

MainWindowのUpdateボタンを二回押した後
![2017-07-02_13h40_55.png](https://qiita-image-store.s3.amazonaws.com/0/32870/5328ab9b-0728-fe04-f6d0-a2606c9fa565.png)

希望の動作にはなっている。

What's the catch?