Logré hacer posible agregar dinámicamente una columna usando solo una línea de código como esta:
MyItemsCollection.AddPropertyDescriptor(
new DynamicPropertyDescriptor<User, int>("Age", x => x.Age));
Con respecto a la pregunta, esta no es una solución basada en XAML (ya que, como se mencionó, no hay una forma razonable de hacerlo), tampoco es una solución que funcione directamente con DataGrid.Columns. Realmente opera con DataGrid enlazado ItemsSource, que implementa ITypedList y, como tal, proporciona métodos personalizados para la recuperación de PropertyDescriptor. En un lugar en el código puede definir "filas de datos" y "columnas de datos" para su cuadrícula.
Si tuvieras:
IList<string> ColumnNames { get; set; }
//dict.key is column name, dict.value is value
Dictionary<string, string> Rows { get; set; }
podrías usar por ejemplo:
var descriptors= new List<PropertyDescriptor>();
//retrieve column name from preprepared list or retrieve from one of the items in dictionary
foreach(var columnName in ColumnNames)
descriptors.Add(new DynamicPropertyDescriptor<Dictionary, string>(ColumnName, x => x[columnName]))
MyItemsCollection = new DynamicDataGridSource(Rows, descriptors)
y la cuadrícula que usa el enlace a MyItemsCollection se completará con las columnas correspondientes. Esas columnas se pueden modificar (nuevas agregadas o eliminadas existentes) en tiempo de ejecución dinámicamente y la cuadrícula actualizará automáticamente su colección de columnas.
DynamicPropertyDescriptor mencionado anteriormente es solo una actualización del PropertyDescriptor normal y proporciona una definición de columnas fuertemente tipada con algunas opciones adicionales. DynamicDataGridSource de lo contrario funcionaría muy bien con un PropertyDescriptor básico.