私は現在、データに応じて列を動的に生成する必要がある C# System.Windows.Controls.DataGrid に取り組んでいます。実行時に列を追加および/または削除できます。
ViewModel クラスで Thread を使用して、DataGrid にフィードする ObservableCollection を更新しています。
私の問題に対して見つけた最良の解決策を説明する投稿を読みました。ただし、DataGridExtension クラスの Columns.CollectionChanged Delegate は InvalideOperationException をスローします。別のスレッドがこのオブジェクトを所有しているため、呼び出しスレッドはこのオブジェクトにアクセスできません。
すべてを描写するためのいくつかのコードを
次に示します。 View XAML
<DataGrid ItemsSource="{Binding CollectionView, Source={StaticResource ViewModel}}" local:DataGridExtension.Columns="{Binding DataGridColumns, Source={StaticResource ViewModel}}" AutoGenerateColumns="False" Name="dataGrid">
ViewModel クラス
public ObservableCollection<DataGridColumn> DataGridColumns
{
get { return columns; }
set { columns = value; }
}
private void getViewData()
{
while (true)
{
Thread.Sleep(1000);
foreach (DataObject data in dataObjects)
{
int index = -1;
foreach (DataGridColumn c in columns)
{
if (c.Header.Equals(column.Header))
index = columns.IndexOf(c);
}
DataGridColumn column = new DataGridTextColumn();
... Creating the column based on data from DataObject ...
DataGridExtension._currentDispatcher = Dispatcher.CurrentDispatcher;
if (index == -1)
{
this.columns.Add(column);
}
else
{
this.columns.RemoveAt(index);
this.columns.Add(column);
}
}
}
}
DataGridExtension クラス
public static class DataGridExtension
{
public static Dispatcher _currentDispatcher;
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.RegisterAttached("Columns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridExtension),
new UIPropertyMetadata(new ObservableCollection<DataGridColumn>(), OnDataGridColumnsPropertyChanged));
private static void OnDataGridColumnsPropertyChanged(DependencyObject iObj, DependencyPropertyChangedEventArgs iArgs)
{
if (iObj.GetType() == typeof(DataGrid))
{
DataGrid myGrid = iObj as DataGrid;
ObservableCollection<DataGridColumn> Columns = (ObservableCollection<DataGridColumn>)iArgs.NewValue;
if (Columns != null)
{
myGrid.Columns.Clear();
if (Columns != null && Columns.Count > 0)
{
foreach (DataGridColumn dataGridColumn in Columns)
{
myGrid.Columns.Add(dataGridColumn);
}
}
Columns.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs args)
{
if (args.NewItems != null)
{
UserControl control = ((UserControl)((Grid)myGrid.Parent).Parent);
foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
{
/// This is where I tried to fix the exception. ///
DataGridColumn temp = new DataGridTextColumn();
temp.Header = column.Header;
temp.SortMemberPath = column.SortMemberPath;
control.Dispatcher.Invoke(new Action(delegate()
{
myGrid.Columns.Add(temp);
}), DispatcherPriority.Normal);
////////////////////////////////////////////////////
}
}
if (args.OldItems != null)
{
foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
{
myGrid.Columns.Remove(column);
}
}
};
}
}
}
public static ObservableCollection<DataGridColumn> GetColumns(DependencyObject iObj)
{
return (ObservableCollection<DataGridColumn>)iObj.GetValue(ColumnsProperty);
}
public static void SetColumns(DependencyObject iObj, ObservableCollection<DataGridColumn> iColumns)
{
iObj.SetValue(ColumnsProperty, iColumns);
}
}
/// を入れたセクション これは、例外を修正しようとした場所です。/// は例外がスローされる場所で、正確には myGrid.add(...);
myGrid オブジェクトでは、その列を DataGrid の列のコレクションに追加できません。これが、Dispatcher.Invoke で囲んだ理由です。奇妙なことに、myGrid.Columns.Add(new DataGridTextColumn()); を実行すると、それは機能し、空の列がビューに追加されているのを見ることができますが、myGrid.Columns.Add(temp); 例外をスローします。
このことで私が捕まえられない何かがあるに違いない。
助けてください!!!!
Stipoの提案に従って編集
UserControl control = ((UserControl)((Grid)myGrid.Parent).Parent);
Columns.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs args)
{
control.Dispatcher.Invoke(new Action(delegate()
{
if (args.NewItems != null)
{
foreach (DataGridColumn column in args.NewItems.Cast<DataGridColumn>())
{
DataGridColumn temp = new DataGridTextColumn();
temp.Header = column.Header;
temp.SortMemberPath = column.SortMemberPath;
myGrid.Columns.Add(temp);
}
}
if (args.OldItems != null)
{
foreach (DataGridColumn column in args.OldItems.Cast<DataGridColumn>())
{
myGrid.Columns.Remove(column);
}
}
}), DispatcherPriority.Normal);
};