Hi Raya,
try following demo:
XAML
<Window x:Class="WpfApp1.Window077"
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:WpfApp077"
mc:Ignorable="d"
Title="211102_RayaChorbadzhiyska-6265" Height="450" Width="800">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ComboBox ItemsSource="{Binding SelectCols}"
DisplayMemberPath="Desc"
SelectedValue="{Binding ColCount}"
SelectedValuePath="ID"/>
<DataGrid Grid.Row="1"
CanUserAddRows="False"
AutoGenerateColumns="False"
ItemsSource="{Binding View}"
local:DataGridExtension.Columns="{Binding Columns}"/>
</Grid>
</Window>
Code:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfApp1
{
public partial class Window077 : Window
{
public Window077() => InitializeComponent();
}
}
namespace WpfApp077
{
public class ViewModel : INotifyPropertyChanged
{
public ViewModel() => cvs.Source = GetData();
#region ComboBox to select ColumnCount in DataGrid
public int MaxColumnCount = 5;
private int _colCount = 1;
public int ColCount { get => this._colCount; set { this._colCount = value; OnPropertyChanged(nameof(Columns)); } }
public List<IDHelper> SelectCols
{
get
{
List<IDHelper> l = new List<IDHelper>();
for (int i = 0; i < MaxColumnCount; i++) l.Add(new IDHelper()
{
ID = i,
Desc = $"{ i + 1 }"
});
return l;
}
}
#endregion
#region View of data in DataGrid
public ICollectionView View { get => cvs.View; }
private CollectionViewSource cvs = new CollectionViewSource();
// create demo data
private ObservableCollection<MapModel> GetData()
{
ObservableCollection<MapModel> data = new ObservableCollection<MapModel>();
for (int i = 0; i < 10; i++)
{
// Array of FKNames
string[] arr1 = new string[MaxColumnCount];
// Array of SomeModels
ObservableCollection<SomeModel>[] arr2 = new ObservableCollection<SomeModel>[MaxColumnCount];
for (int k = 0; k < MaxColumnCount; k++) // for columns in DataGrid
{
// collection in array of SameModels
arr2[k] = new ObservableCollection<SomeModel>();
for (int l = 0; l < 5; l++) arr2[k].Add(new SomeModel() { ID = l, Name = $"FKName {l} {k} {i}" });
// first element
arr1[k] = arr2[k][0].Name;
}
//
data.Add(new MapModel(arr1, arr2) { Name = $"Name {i}" });
}
return data;
}
#endregion
#region Columns in DataGrid
public ObservableCollection<DataGridColumn> Columns { get => GetColumns(); }
private ObservableCollection<DataGridColumn> GetColumns()
{
ObservableCollection<DataGridColumn> cols = new ObservableCollection<DataGridColumn>();
cols.Add(new DataGridTextColumn() { Header = "First", Width = 100, Binding = new Binding("Name") });
for (int i = 0; i <= ColCount; i++)
{
DataGridTemplateColumn col = new DataGridTemplateColumn() { Header = $"Second {i + 1}", Width = 100 };
// SecondCellTemplate
DataTemplate dt1 = new DataTemplate();
FrameworkElementFactory tb = new FrameworkElementFactory(typeof(TextBlock));
tb.SetBinding(TextBlock.TextProperty, new Binding($"FKName[{i}]") { Mode = BindingMode.OneWay });
dt1.VisualTree = tb;
col.CellTemplate = dt1;
// SecondCellEditingTemplate
DataTemplate dt2 = new DataTemplate();
FrameworkElementFactory cb = new FrameworkElementFactory(typeof(ComboBox));
cb.SetValue(ComboBox.DisplayMemberPathProperty, "Name");
cb.SetBinding(ComboBox.ItemsSourceProperty, new Binding($"SomeValues[{i}]") { Mode = BindingMode.OneWay });
cb.SetBinding(ComboBox.SelectedValueProperty, new Binding($"FKName[{i}]") { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
cb.SetValue(ComboBox.SelectedValuePathProperty, "Name");
dt2.VisualTree = cb;
col.CellEditingTemplate = dt2;
//
cols.Add(col);
}
return cols;
}
#endregion
#region OnPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
#endregion
}
public class MapModel
{
public string Name { get; set; }
public ArrayIndexer<int> FK { get; } // Name of selected SomeValue
public ArrayIndexer<string> FKName { get; } // Name of selected SomeValue
public ArrayIndexer<ObservableCollection<SomeModel>> SomeValues { get; }
public MapModel(string[] FKNameArray, ObservableCollection<SomeModel>[] SomeValuesArray)
{
this.FKNameArr = FKNameArray;
this.SomeValuesArr = SomeValuesArray;
this.FKName = new ArrayIndexer<string>(FKNameArr);
this.SomeValues = new ArrayIndexer<ObservableCollection<SomeModel>>(SomeValuesArr);
}
string[] FKNameArr;
ObservableCollection<SomeModel>[] SomeValuesArr;
}
public class SomeModel
{
public int ID { get; set; }
public string Name { get; set; }
}
public class IDHelper
{
public int ID { get; set; }
public string Desc { get; set; }
}
public class ArrayIndexer<T>
{
private T[] arr;
public ArrayIndexer(T[] arr) => this.arr = arr;
public T this[int index] { get => arr[index]; set { arr[index] = value; } }
public int Length { get => arr.Length; }
}
public static class DataGridExtension
{
public static ObservableCollection<DataGridColumn> GetColumns(DependencyObject obj) => (ObservableCollection<DataGridColumn>)obj.GetValue(ColumnsProperty);
public static void SetColumns(DependencyObject obj, ObservableCollection<DataGridColumn> value) => obj.SetValue(ColumnsProperty, value);
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.RegisterAttached("Columns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridExtension),
new UIPropertyMetadata(new ObservableCollection<DataGridColumn>(),
OnDataGridColumnsPropertyChanged));
private static void OnDataGridColumnsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d.GetType() == typeof(DataGrid))
{
DataGrid myGrid = d as DataGrid;
ObservableCollection<DataGridColumn> Columns = (ObservableCollection<DataGridColumn>)e.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) foreach (DataGridColumn column in args.NewItems) myGrid.Columns.Add(column);
if (args.OldItems != null) foreach (DataGridColumn column in args.OldItems) myGrid.Columns.Remove(column);
};
}
}
}
}
}
Result: