状況:
WPF/C# では、.xaml ファイルのリソースで次の DataTemplate を使用します。
<DataTemplate x:Key="lComboTestTemplate2">
<ComboBox Name="lComboBoxInTemplate" VerticalAlignment="Center" ItemsSource="{Binding WrapperCollection[0].ComboBoxList}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Width="20" />
<TextBlock Text="{Binding}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
コードビハインドでは、次のように問題なく読み取りました。
DataTemplate lMyCellEditingTemplate = (DataTemplate)Resources["lComboTestTemplate2"];
そして実際に使えるようになりました。コードビハインドでこの同じデータテンプレートを実際に実現しようとすると、問題が発生します。
public DataTemplate CreateComboBoxDataTemplate(Type type, int aNumber)
{
StringReader stringReader = new StringReader(
@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
<" + type.Name + @" ItemsSource=""{Binding WrapperCollection[" + aNumber.ToString() + @"].ComboBoxList}"">
<" + type.Name + @".ItemTemplate>
<DataTemplate>
<StackPanel Orientation=""HorizontalAlignment"">
<CheckBox Width=""20"" />
<TextBlock Text=""{Binding .}"" VerticalAlignment=""Center"" />
</StackPanel>
</DataTemplate>
</" + type.Name + @".ItemTemplate>
</" + type.Name + @" >
</DataTemplate>");
XmlReader xmlReader = XmlReader.Create(stringReader);
return XamlReader.Load(xmlReader) as DataTemplate;
}
コンパイルして実際に実行しますが、データグリッドの編集を開始すると、nullpointer 例外が発生します。
質問
これが nullpointer である理由がわかりません。同じ Xaml コードが機能するのに、コード ビハインドが機能しない理由を誰か教えてください。
残りのコード/コンテキスト
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LoadData();
Counter = 0;
this.DataContext = RowList;
}
private void LoadData()
{
RowList = new ObservableCollection<RowObject>();
WrapperObject lWrapperObject1 = new WrapperObject();
lWrapperObject1.Value = 1;
WrapperObject lWrapperObject2 = new WrapperObject();
lWrapperObject2.Value = 2;
WrapperObject lWrapperObject3 = new WrapperObject();
lWrapperObject3.Value = 3;
WrapperObject lWrapperObject4 = new WrapperObject();
lWrapperObject4.Value = 4;
WrapperObject lWrapperObject6 = new WrapperObject();
lWrapperObject6.Value = 6;
WrapperObject lWrapperObject8 = new WrapperObject();
lWrapperObject8.Value = 8;
RowObject lRowObject1 = new RowObject();
lRowObject1.RowObjectName = "RowObject1";
lRowObject1.WrapperCollection.Add(lWrapperObject1);
lRowObject1.WrapperCollection.Add(lWrapperObject2);
lRowObject1.WrapperCollection.Add(lWrapperObject6);
RowObject lRowObject2 = new RowObject();
lRowObject2.RowObjectName = "RowObject2";
lRowObject2.WrapperCollection.Add(lWrapperObject3);
lRowObject2.WrapperCollection.Add(lWrapperObject4);
lRowObject2.WrapperCollection.Add(lWrapperObject8);
RowList.Add(lRowObject1);
RowList.Add(lRowObject2);
}
public ObservableCollection<RowObject> RowList { get; set; }
public int Counter { get; set; }
private void Button_Click(object sender, RoutedEventArgs e)
{
DataGridTemplateColumn lTemplateColumn = new DataGridTemplateColumn();
lTemplateColumn.Header = "NewDynamicColumn";
TextBlock textBlock = new TextBlock();
var lMyCellTemplate = CreateDataTemplate(textBlock.GetType(), Counter);
var lMyCellEditingTemplate = CreateComboBoxDataTemplate(lCombo.GetType(), 0);
//var lMyCellEditingTemplate = (DataTemplate)Resources["lComboTestTemplate2"];
lTemplateColumn.CellTemplate =lMyCellTemplate;
lTemplateColumn.CellEditingTemplate = lMyCellEditingTemplate;
this.MyGrid.Columns.Add(lTemplateColumn);
Counter++;
}
public DataTemplate CreateDataTemplate(Type type, int aNumber)
{
StringReader stringReader = new StringReader(
@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
<" + type.Name + @" Text=""{Binding WrapperCollection[" + aNumber.ToString() + @"].Value}""/>
</DataTemplate>");
XmlReader xmlReader = XmlReader.Create(stringReader);
return XamlReader.Load(xmlReader) as DataTemplate;
}
public class RowObject : INotifyPropertyChanged
{
public RowObject()
{
WrapperCollection = new ObservableCollection<WrapperObject>();
}
public ObservableCollection<WrapperObject> WrapperCollection { get; set; }
private string fRowObjectName;
public string RowObjectName
{
get { return fRowObjectName; }
set
{
fRowObjectName = value;
RaisePropertyChanged("RowObjectName");
}
}
#region Notify property changed
public event PropertyChangedEventHandler PropertyChanged;
private int fMyIndex;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
public class WrapperObject : INotifyPropertyChanged
{
public WrapperObject()
{
counter++;
ComboBoxList = new List<string>();
ComboBoxList.Add((10 + counter).ToString());
ComboBoxList.Add((20 + counter).ToString());
}
private static int counter = 0;
private int fValue;
private List<String> fComboBoxList;
public int Value
{
get {return fValue;}
set
{
fValue = value;
RaisePropertyChanged("Value");
}
}
public List<string> ComboBoxList
{
get { return fComboBoxList; }
set
{
fComboBoxList = value;
RaisePropertyChanged("ComboBoxList");
}
}
#region Notify property changed
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
.Xaml
<Window.Resources>
<DataTemplate x:Key="lComboTestTemplate">
<StackPanel Orientation="Horizontal">
<CheckBox Width="20" />
<TextBlock Text="{Binding WrapperCollection[1].ComboBoxList}" Width="100" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="lComboTestTemplate2">
<ComboBox Name="lComboBoxInTemplate" VerticalAlignment="Center" ItemsSource="{Binding WrapperCollection[0].ComboBoxList}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Width="20" />
<TextBlock Text="{Binding}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</Window.Resources>
<StackPanel>
<DataGrid x:Name="MyGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding}"
>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding RowObjectName}"/>
<!--<DataGridTextColumn Header="ExampleColumn1" Binding="{Binding WrapperCollection[0].Value}"/>-->
</DataGrid.Columns>
</DataGrid>
<Button Content="Click" Click="Button_Click" Width="100" Margin="20"/>
</StackPanel>