EDIT Solved:
Due to the insight of answers and comments I was able to find a solution that fits my needs. Due to the fact that the data grid is created dynamically and reused within a loop so that it can be inserted in the treeview, most of the things I needed to do could not be done in XML(to my knowledge, spent half a day trying to find a way to make that work and it just wasn't happening.) Due to HighCore's belittling of my code(which was necessary and based on fact, but had me licking my wounds as I was proud of it) I moved on to a Data Binding approach. If you have not the patience to read the rest of this paragraph the code sample is below. It made my code much cleaner and allowed my to add Binded DataGridTextColumns to the DataGrid that could be formatted with an in code setter. I was able to create the setter in code by referencing Sheridan's answer which gave me everything I needed. Code Below.
while (bc.next != null)
{
bc = bc.next;
System.Windows.Controls.DataGrid dgbc = new System.Windows.Controls.DataGrid()
dgbc.AutoGenerateColumns = false;
Style style = new Style(typeof(System.Windows.Controls.DataGridCell));
Setter setter = new Setter(System.Windows.Controls.DataGridCell.HorizontalAlignmentProperty, System.Windows.HorizontalAlignment.Right);
style.Setters.Add(setter);
DataGridTextColumn dgtc = new DataGridTextColumn();
dgtc.Binding = new System.Windows.Data.Binding("pBudgetCode");
dgtc.Header = "Budget Code";
dgbc.Columns.Add(dgtc);
DataGridTextColumn dgtc2 = new DataGridTextColumn();
dgtc2.Binding = new System.Windows.Data.Binding("pOriginalEstimate");
dgtc2.CellStyle = style;
dgtc2.Header = "Original Estimate";
dgbc.Columns.Add(dgtc2);
//More Columns added, dgtc above intentionally did not use the style.
LinkedList<BudgetCodeCTC> tempCode = new LinkedList<BudgetCodeCTC>();
tempCode.AddLast(bc.getCTCProps());
dgbc.ItemsSource = tempCode;
//BudgetCodeCTC is the class that contains the properties to be bound.
//The paramater in creation of the Binding object is the name of the Property in BudgetCodeCTC that the column is bound to.
foreach(BudgetCategoryCTC catCTC in tempCode.ElementAt(0).pAccumulateAs)
{
//Essentially same code as above except applied at the next level down in the TreeView and then added to the Parent TreeViewItem
//Another foreach loop for the next level down using essentially the same code
}
I know that is only a snapshot of the code but hopefully it provides enough information to someone looking for a similar solution.
Example of what this looks like:
Also winforms is referenced as they are used in the omitted areas because of an end users preference(Fought the good fight and lost). I removed some of the System.Windows.Controls So you wouldn't have to scroll the codebox too far, I assure you the code compiles and runs.
while (bc.next != null)
{
bc = bc.next;
budgetCodeCategory mat = bc.materials;
budgetCodeCategory equ = bc.equipment;
budgetCodeCategory sub = bc.sub;
budgetCodeCategory oth = bc.other;
budgetCodeCategory lab = bc.labor;
budgetCodeCategory ovh = bc.overhead;
DataTable t = new DataTable();
t.Columns.Add("Budget Code", typeof(String));
t.Columns.Add("Original Estimate", typeof(Decimal));
t.Columns.Add("Approved Owner Changes", typeof(Decimal));
t.Columns.Add("Total Estimate", typeof(Decimal));
t.Columns.Add("Job-To-Date Costs", typeof(Decimal));
t.Columns.Add("% Complete", typeof(Decimal));
t.Columns.Add("Cost To Complete", typeof(Decimal));
t.Columns.Add("Revised Cost At Completion", typeof(Decimal));
t.Columns.Add("Total Estimate Variance", typeof(Decimal));
//Row Added Here
DataView dvbc = new DataView(t);
DataGrid dgbc = new System.Windows.Controls.DataGrid();
dgbc.ItemsSource = dvbc;
TreeViewItem tvbc = new TreeViewItem() { Header = dgbc };
tvbc.UpdateLayout();
if (mat.first != null)
{
DataTable ct = new DataTable();
ct.Columns.Add("Category", typeof(String));
ct.Columns.Add("Original Estimate", typeof(Decimal));
ct.Columns.Add("Approved Owner Changes", typeof(Decimal));
ct.Columns.Add("Total Estimate", typeof(Decimal));
ct.Columns.Add("Job-To-Date Costs", typeof(Decimal));
ct.Columns.Add("% Complete", typeof(Decimal));
ct.Columns.Add("Cost To Complete", typeof(Decimal));
ct.Columns.Add("Revised Cost At Completion", typeof(Decimal));
ct.Columns.Add("Total Estimate Variance", typeof(Decimal));
//Row Added Here
ct.AcceptChanges();
DataView dv = new DataView(ct);
DataGrid dg = new System.Windows.Controls.DataGrid();
dg.ItemsSource = dv;
TreeViewItem tvi = new TreeViewItem() { Header = dg };
tvi.UpdateLayout();
tvbc.Items.Add(tvi);
if (mat.first.next != null)
{
mat = mat.first;
Boolean myHeader = true;
while (mat.next != null)
{
mat = mat.next;
DataTable ctch = new DataTable();
ctch.Columns.Add("Category", typeof(String));
ctch.Columns.Add("Original Estimate", typeof(Decimal));
ctch.Columns.Add("Approved Owner Changes", typeof(Decimal));
ctch.Columns.Add("Total Estimate", typeof(Decimal));
ctch.Columns.Add("Job-To-Date Costs", typeof(Decimal));
ctch.Columns.Add("% Complete", typeof(Decimal));
ctch.Columns.Add("Cost To Complete", typeof(Decimal));
ctch.Columns.Add("Revised Cost At Completion", typeof(Decimal));
ctch.Columns.Add("Total Estimate Variance", typeof(Decimal));
//Row Added Here
ctch.AcceptChanges();
DataView dvc = new DataView(ctch);
DataGrid dgc = new System.Windows.Controls.DataGrid();
dgc.ItemsSource = dvc;
TreeViewItem tvic = new TreeViewItem() { Header = dgc };
tvic.UpdateLayout();
tvi.Items.Add(tvic);
}
}
}
}
//This if statement is repeated 5 more times for other Children of tvi. That code is Identical to what is shown here(omitted Row add is different).
//This is the end of the relevant code
I apologize for the long code sample.
So my issue is that this all goes down in the Constructor for the window. At the end of the scope of the DataGrid variable it has no Columns which I need to format the columns to allign right. However when an event is fired from the DataGrid and I get the Count on the Columns from the sender that was cast to DataGrid it shows as having 9 Columns(the correct number)
I tried using the AutoGeneratingColumn and AutoGeneratedColumns events to find out when the DataGrid initialized its columns and the events never fired.
If anyone could shed some light on a way to not have to have an event fired to format the columns it would really help, it's getting to the point where I may have to push back release(internal only, we do not release public software) due to this problem as I am cleaning up the formatting so that it can look clean for testing.
Thanks for your time.
You really shouldn't be doing stuff like this in code. It's much easier if you define your DataGrid.Columns
in XAML, data bind to the DataGrid.ItemsSource
property and just update the data bound collection from code. You can easily right align a DataGridTextColumn
in XAML like this:
<DataGridTextColumn Binding="{Binding SomeNumericColumn}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
UPDATE >>>
The Style
can be re-used, but we generally define each of the columns in a DataGrid
:
<Style Name="RightAlign" TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
...
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding SomeTextColumn}" />
<DataGridTextColumn Binding="{Binding SomeNumericColumn}"
ElementStyle="{StaticResource RightAlign}" ... />
<DataGridTextColumn Binding="{Binding AnotherTextColumn}" />
...
</DataGrid.Columns>