Как выровнять числовые столбцы DataGrid справа в коде?

РЕДАКТИРОВАТЬ Решено:

Благодаря пониманию ответов и комментариев я смог найти решение, которое соответствует моим потребностям. Из-за того, что сетка данных создается динамически и повторно используется в цикле, так что ее можно вставить в древовидную структуру, большинство вещей, которые мне нужно было сделать, не могли быть выполнены в XML(насколько я знаю, я потратил полдня на попытки чтобы найти способ заставить это работать, а этого просто не было.) Из-за принижения HighCore моего кода (который был необходим и основан на фактах, но заставил меня зализывать свои раны, поскольку я гордился этим), я перешел к Подход связывания данных. Если у вас нет терпения прочитать остальную часть этого абзаца, пример кода приведен ниже. Это сделало мой код намного чище и позволило добавить Binded DataGridTextColumns в DataGrid, который можно отформатировать с помощью установщика кода. Я смог создать сеттер в коде, сославшись на ответ Шеридана, который дал мне все, что мне было нужно. Код ниже.

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
    }

Я знаю, что это всего лишь снимок кода, но, надеюсь, он предоставит достаточно информации тому, кто ищет подобное решение.

Пример того, как это выглядит:

  • Я пропустил некоторые вещи и объяснил простую версию того, что опущено в комментариях, обозначенных //
  • Хотя циклические тесты выполняются для объектов, использующих.next, чтобы добавить возможность связанного списка к объекту без дополнительных накладных расходов (я знаю, что делаю это в меньшинстве вместо использования LinkedList<>, я сомневаюсь, что смогу убедить Вы используете мой путь, и я знаю, что вы не убедите меня).
  • Также на winforms ссылаются, так как они используются в пропущенных областях из-за предпочтения конечных пользователей (боролся за хороший бой и проиграл). Я удалил некоторые из элементов System.Windows.Controls. Чтобы вам не пришлось слишком долго прокручивать кодовую коробку, уверяю вас, код компилируется и запускается.

            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
    

Я прошу прощения за длинный пример кода.

Так что моя проблема в том, что все это происходит в конструкторе для окна. В конце области видимости переменной DataGrid у нее нет столбцов, которые мне нужны для форматирования столбцов, чтобы они выравнивались вправо. Однако, когда событие запускается из DataGrid, и я получаю Счетчик столбцов от отправителя, который был приведен к DataGrid, он показывает, что имеет 9 столбцов (правильное число)

Я попытался использовать события AutoGeneratingColumn и AutoGeneratedColumns, чтобы выяснить, когда DataGrid инициализировал свои столбцы и события никогда не запускались.

Если кто-то может пролить некоторый свет на то, чтобы не нужно было запускать событие для форматирования столбцов, это действительно помогло бы, то это привело к тому, что мне, возможно, пришлось бы отодвинуть релиз (только для внутреннего использования, мы не выпускаем общедоступное программное обеспечение) из-за этой проблемы, поскольку я очищаю форматирование, чтобы оно выглядело чистым для тестирования.

Спасибо за ваше время.

1 ответ

Решение

Вы действительно не должны делать такие вещи в коде. Это намного проще, если вы определите DataGrid.Columns в XAML данные связываются с DataGrid.ItemsSource свойство и просто обновить привязанную к данным коллекцию из кода. Вы можете легко выровнять DataGridTextColumn в XAML вот так:

<DataGridTextColumn Binding="{Binding SomeNumericColumn}">
    <DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="HorizontalAlignment" Value="Right" />
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn> 

ОБНОВЛЕНИЕ >>>

Style можно использовать повторно, но мы обычно определяем каждый из столбцов в 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>
Другие вопросы по тегам