WPFで動的にユーザーコントロールを追加したときに、値を設定する方法がわからない

実現したいこと

以下のような画面を作成しています。
・データ行は画面起動時の引数によって可変
・すべてのコンボボックスのデータは同じもの
・チェックボックスがONのときは横のコンボボックスが有効
・チェックボックスがOFFのときは各データのコンボボックスが有効
ここまでは実装しました。

次に、画面起動時に各コンボボックスにデータを設定したいのですが方法がわかりません。

イメージ説明

発生している問題・分からないこと

現在はチェックボックスとその横にあるコンボボックスがあるウィンドウを用意し、その下にユーザーコントロールを追加しています。
各ユーザーコントロールにあるコンボボックスに値を設定したのですが、今のコードではVM側からはユーザーコントロールのオブジェクトを認識できないため設定できません。何か方法はありませんでしょうか?

該当のソースコード

MainWindow.xaml

1 <Window.DataContext> 2 <vm:MainViewModel/> 3 </Window.DataContext> 4 <Window.Resources> 5 <vm:CBoolNegativeConverter x:Key="BoolNeg"/> 6 </Window.Resources> 7 <Grid> 8 <Grid.RowDefinitions> 9 <RowDefinition Height="1cm"/> 10 <RowDefinition Height="1cm"/> 11 <RowDefinition Height="Auto"/> 12 </Grid.RowDefinitions> 13 <Grid.ColumnDefinitions> 14 <ColumnDefinition /> 15 <ColumnDefinition /> 16 <ColumnDefinition /> 17 </Grid.ColumnDefinitions> 18 <TextBlock Grid.Row="0" Grid.Column="1" Text="項目1" HorizontalAlignment="Center" VerticalAlignment="Center"/> 19 <TextBlock Grid.Row="0" Grid.Column="2" Text="項目2" HorizontalAlignment="Center" VerticalAlignment="Center"/> 20 <CheckBox Grid.Row="1" Grid.Column="0" IsChecked="{Binding IsCheck}" HorizontalAlignment="Center" VerticalAlignment="Center"/> 21 <ComboBox Grid.Row="1" Grid.Column="2" 22 IsEnabled="{Binding IsCheck}" 23 SelectedItem="{Binding SelectedAllItem}" 24 ItemsSource="{Binding DataItems}"/> 25 <StackPanel x:Name="DataPanel" Grid.Row="2" Grid.ColumnSpan="3"/> 26 </Grid> 27</Window> 28

MainWindow.xaml.cs

1namespace WpfApp4 2{ 3 /// <summary> 4 /// MainWindow.xaml の相互作用ロジック 5 /// </summary> 6 public partial class MainWindow : Window 7 { 8 public MainWindow() 9 { 10 InitializeComponent(); 11 12 int dataCounter = 3; //引数によって変動 13 14 for(int i = 0; i < dataCounter; i++) 15 { 16 var tmpUC = new UserControl1(i,"test", this); 17 tmpUC.UCTitle.Content = "Data" + i.ToString(); 18 DataPanel.Children.Add(tmpUC); 19 } 20 } 21 } 22} 23

UserControl1.xaml

1<UserControl x:Class="WpfApp4.UserControl1" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:WpfApp4" 7 xmlns:vm="clr-namespace:WpfApp4.ViewModels" 8 mc:Ignorable="d" 9 d:DesignHeight="76" d:DesignWidth="581"> 10 <UserControl.Resources> 11 <vm:CBoolNegativeConverter x:Key="BoolNeg"/> 12 </UserControl.Resources> 13 <Grid> 14 <Grid.ColumnDefinitions> 15 <ColumnDefinition /> 16 <ColumnDefinition /> 17 <ColumnDefinition /> 18 </Grid.ColumnDefinitions> 19 <Label Grid.Column="0" 20 x:Name="UCTitle" 21 HorizontalAlignment="Center"/> 22 <ComboBox Grid.Column="1" 23 Margin="5,0" 24 SelectedItem="{Binding DisplayData1Info}" 25 ItemsSource="{Binding DisplayData1Items}" 26 DisplayMemberPath="Data"/> 27 <ComboBox Grid.Column="2" 28 Margin="0" 29 IsEnabled="{Binding Path=IsCheck, Converter={StaticResource BoolNeg}}" 30 SelectedItem="{Binding DisplayData2Info}" 31 ItemsSource="{Binding DisplayData2Items}" 32 DisplayMemberPath="Data"/> 33 </Grid> 34</UserControl> 35

UserControl1.xaml.cs

1namespace WpfApp4 2{ 3 /// <summary> 4 /// UserControl1.xaml の相互作用ロジック 5 /// </summary> 6 public partial class UserControl1 : UserControl 7 { 8 public UserControl1() 9 { 10 this.DataContext = new ViewModels.MainViewModel(); 11 InitializeComponent(); 12 } 13 14 public UserControl1(int ItemNumber, string row, MainWindow main) 15 { 16 main.DataContext = new ViewModels.MainViewModel(ItemNumber); 17 InitializeComponent(); 18 19 } 20 } 21} 22

MainViewModel.cs

1namespace WpfApp4.ViewModels 2{ 3 4 public class CBoolNegativeConverter : IValueConverter 5 { 6 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 7 { 8 return !(value is bool && (bool)value); 9 } 10 11 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 12 { 13 return !(value is bool && (bool)value); 14 } 15 16 } 17 18 class MainViewModel : NotificationObject 19 { 20 public string[] DataList = new string[] 21 { 22 "test1", 23 "test2", 24 "test3", 25 }; 26 27 public class DisplayDataInfo 28 { 29 public DisplayDataInfo(string data, int item1, int item2) 30 { 31 Data = data; 32 Item1 = item1; 33 Item2 = item2; 34 } 35 36 public string Data { get; set; } 37 public int Item1 { get; set; } //項目1 38 public int Item2 { get; set; } //項目2 39 } 40 41 42 public MainViewModel() 43 { 44 DataItems = DataList; 45 } 46 47 public MainViewModel(int ItemNumber) 48 { 49 foreach(var data in DataList) 50 { 51 DisplayData1Items.Add(new DisplayDataInfo(data, ItemNumber + 1, 0)); 52 DisplayData2Items.Add(new DisplayDataInfo(data, ItemNumber + 1, 1)); 53 } 54 55 //テストデータ 56 bool flg = true; 57 string allItem = DataList[1]; 58 string data1Item1 = DataList[0]; 59 string data2Item1 = DataList[1]; 60 string data3Item1 = DataList[2]; 61 string data1Item2 = DataList[1]; 62 63 //各データに値を設定 64 if (flg) 65 { 66 IsCheck = flg; 67 SelectedAllItem = allItem; 68 69 //どのように代入すればいいのかわからない 70 //対象のユーザーコントロールを指定して 71 //DisplayData1Info = DataList[0];ように代入すればよい? 72 } 73 else 74 { 75 //同じく 76 } 77 78 } 79 80 public string[] DataItems 81 { 82 get { return DataList; } 83 set 84 { 85 DataList = value; 86 RaisePropertyChanged("DataItems"); 87 } 88 } 89 90 /// <summary> 91 /// 全体リスト 92 /// </summary> 93 public ObservableCollection<DisplayDataInfo> DisplayDataItems { get; } = new ObservableCollection<DisplayDataInfo>(); 94 95 /// <summary> 96 /// 項目1リスト 97 /// </summary> 98 public ObservableCollection<DisplayDataInfo> DisplayData1Items { get; } = new ObservableCollection<DisplayDataInfo>(); 99 100 /// <summary> 101 /// 項目2リスト 102 /// </summary> 103 public ObservableCollection<DisplayDataInfo> DisplayData2Items { get; } = new ObservableCollection<DisplayDataInfo>(); 104 105 106 private bool _IsCheck = false; 107 public bool IsCheck 108 { 109 get { return _IsCheck; } 110 set 111 { 112 if (_IsCheck != value) 113 { 114 _IsCheck = value; 115 RaisePropertyChanged("IsCheck"); 116 } 117 } 118 } 119 120 private string _SelectedAllItem; 121 public string SelectedAllItem 122 { 123 get { return _SelectedAllItem; } 124 set 125 { 126 if (_SelectedAllItem != value) 127 { 128 _SelectedAllItem = value; 129 RaisePropertyChanged("SelectedAllItem"); 130 } 131 } 132 } 133 134 /// <summary> 135 /// 項目1の選択肢 136 /// </summary> 137 private DisplayDataInfo _DisplayData1Info = null; 138 public DisplayDataInfo DisplayData1Info 139 { 140 get { return _DisplayData1Info; } 141 set 142 { 143 if (_DisplayData1Info != value) 144 { 145 RaisePropertyChanged("DisplayData1Info"); 146 } 147 148 } 149 } 150 151 /// <summary> 152 /// 項目2の選択肢 153 /// </summary> 154 private DisplayDataInfo _DisplayData2Info = null; 155 public DisplayDataInfo DisplayData2Info 156 { 157 get { return _DisplayData2Info; } 158 set 159 { 160 if (_DisplayData2Info != value) 161 { 162 RaisePropertyChanged("DisplayData2Info"); 163 } 164 } 165 } 166 167 } 168} 169

試したこと・調べたこと

上記の詳細・結果

そもそもウィンドウとユーザーコントロールのVMを共通しているのがいけないのでしょうか?
MVVMに強いこだわりはないので、ユーザーコントロール部分をウィンドウのコードビハインドで記述してしまえばできそうとは考えています。

補足

visual studio 2017
.net framework 4.7.2

コメントを投稿

0 コメント