Thankfully, the Dev Express GridColumn class is a DependencyObject, and all the needed properties are exposed as DependencyProperty's.
Since the detail grid has the same data interface as the master grid, I was even able to clone the column definitions.
Finally, since this was an MVVM project, I didn't want the functionality in code-behind, so I abstracted the code for this into a Behavior
The approach was to bind the Width, Visibility, and VisibleIndex properties of each master grid column to a cloned detail grid column, giving the two entities the appearance of being one functional entity.
Here's the snippet representing the detail grid definition....
<dxg:GridControl>
<!-- Master grid defined here, not shown. Detail grid below -->
<dxg:GridControl.DetailDescriptor>
<dxg:DataControlDetailDescriptor ItemsSourceBinding="{Binding Details}">
<dxg:GridControl x:Name="DetailsGrid" AutoGenerateColumns="None" ColumnsSource="{StaticResource ColumnsCollection}" >
<dxg:GridControl.View >
<dxg:TableView AutoWidth="False"
AllowCascadeUpdate="False"
AllowFixedGroups="True"
ShowGroupPanel="False"
CellStyle="{StaticResource
DefaultCellStyle}"
NavigationStyle="Row"
ShowGroupedColumns="True"
AllowGrouping="True"
AllowEditing="False"
AllowScrollAnimation="False"
ShowFixedTotalSummary="False"
AllowHorizontalScrollingVirtualization="True"
HorizontalScrollbarVisibility="Auto"
RowStyle="{StaticResource RowStyle}"
AlternateRowBackground="{x:Static dxRes:DevExpressResources.AlternateRowBackgroundBrush}"
UseLightweightTemplates="None"
ShowColumnHeaders="False"
/>
</dxg:GridControl.View>
<i:Interaction.Behaviors>
<local:SyncDetailGridColumnsBehavior/>
</i:Interaction.Behaviors>
</dxg:GridControl>
</dxg:DataControlDetailDescriptor>
</dxg:GridControl.DetailDescriptor>
</dxg:GridControl>
Note the highlighted part above that introduces a local class called SyncDetailGridColumsBehavior, shown in its entirety below:
using System.Windows.Data;
using System.Windows.Interactivity;
using DevExpress.Xpf.Grid;
namespace Local
{
public class SyncDetailGridColumnsBehavior : Behavior<GridControl>
{
private GridColumnCollection
_parentGridColumns;
private GridColumnCollection
_detailsGridColumns;
protected override void OnAttached()
{
_detailsGridColumns = AssociatedObject.Columns;
_parentGridColumns = AssociatedObject.ResolveParentColumnCollection();
InitializeMasterDetailGrid();
}
private void InitializeMasterDetailGrid()
{
_detailsGridColumns.CloneColumnsAndBindWidthsFrom(_parentGridColumns);
}
}
internal static class ColumnHelpers
{
public static GridColumnCollection
ResolveParentColumnCollection(this GridControl associatedObject)
{
var result =
((DevExpress.Xpf.Grid.GridControl)
((System.Windows.FrameworkContentElement) associatedObject.Parent).Parent).Columns;
return result;
}
public static void
CloneColumnsAndBindWidthsFrom(this GridColumnCollection targetGridColumns,
GridColumnCollection sourceGrid)
{
targetGridColumns.Clear();
foreach (var aSourceColumn in sourceGrid)
{
var aClonedColumn =
aSourceColumn.Clone();
aSourceColumn.BindWidths(aClonedColumn);
aSourceColumn.BindPositions(aClonedColumn);
targetGridColumns.Add(aClonedColumn);
}
}
public static GridColumn Clone(this GridColumn source)
{
return new GridColumn()
{
Name = source.Name,
Width = source.Width,
Binding = source.Binding,
Header = source.Header,
Style = source.Style,
CellStyle = source.CellStyle,
CellTemplateSelector = source.CellTemplateSelector,
CellTemplate = source.CellTemplate,
};
}
public static void BindWidths(this GridColumn source, GridColumn bindingPartner)
{
source.SetBinding(BaseColumn.WidthProperty,
new Binding("ActualWidth")
{
Source = bindingPartner,
Mode = BindingMode.OneWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
bindingPartner.SetBinding(BaseColumn.WidthProperty,
new Binding("ActualWidth")
{
Source = source,
Mode = BindingMode.OneWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
}
public static void BindPositions(this GridColumn source, GridColumn bindingPartner)
{
source.SetBinding(BaseColumn.VisibleIndexProperty,
new Binding("VisibleIndex")
{
Source = bindingPartner,
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
}
public static void BindVisibility(this GridColumn source, GridColumn bindingPartner)
{
source.SetBinding(BaseColumn.VisibleProperty,
new Binding("Visible")
{
Source = bindingPartner,
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
}
}
}
In the meantime, let me know how this makes ya feel... leave a comment, below.
Thanks!