1

i'm working on a new program that will show information about Test on some Tools in my factory. For doing that i'm creating a DataGrid Control at run time and populate it.This part is working very well.

My problem is to add RowDetails, How can i do that in code behind?

if (datatable.Rows.Count != 0)
    {
      foreach (DataRow dt in datatable.Rows)
        {
          if (last_tool_test == "" || last_tool_test != dt[1].ToString())
             {
               last_tool_test = dt[1].ToString();
               txt = new TextBlock();
               txt.Text = dt[1].ToString() + " :";
               txt.TextDecorations = TextDecorations.Underline;
               txt.HorizontalAlignment = HorizontalAlignment.Center;
               txt.Margin = new Thickness(0, 0, 0, 7);

               data = new DataGrid();
               data.Width = double.NaN;
               data.Margin = new Thickness(5, 0, 5, 5);
               data.HeadersVisibility = DataGridHeadersVisibility.Column;
               data.CanUserAddRows = false;
               data.CanUserDeleteRows = false;
               data.CanUserReorderColumns = false;
               data.CanUserResizeColumns = false;
               data.CanUserSortColumns = false;
               data.IsReadOnly = true;
               data.SelectionMode = DataGridSelectionMode.Extended;
               DataGridTextColumn col1 = new DataGridTextColumn();
               col1.Header = "Recipe Name";
               col1.Binding = new Binding("Recipe_Name");
               col1.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
               var style = new Style(typeof(DataGridColumnHeader));
               style.Setters.Add(new Setter()
               {
                Property = HorizontalAlignmentProperty,
                Value = HorizontalAlignment.Stretch
               });
               style.Setters.Add(new Setter()
               {
                Property = HorizontalContentAlignmentProperty,
                Value = HorizontalAlignment.Center
               });
               style.Setters.Add(new Setter()
               {
                Property = FontWeightProperty,
                Value = FontWeights.Bold
               });
               var style1 = new Style(typeof(TextBlock));
               style1.Setters.Add(new Setter()
               {
                Property = HorizontalAlignmentProperty,
                Value = HorizontalAlignment.Center
               });
               col1.HeaderStyle = style;
               col1.ElementStyle = style1;
               data.Columns.Add(col1);
               DataGridTextColumn col2 = new DataGridTextColumn();
               col2.Header = "Foup";
               col2.Width = 100;
               col2.Binding = new Binding("Foup");
               col2.HeaderStyle = style;
               col2.ElementStyle = style1;
               data.Columns.Add(col2);
               DataGridTextColumn col3 = new DataGridTextColumn();
               col3.Header = "Need Reference?";
               col3.Width = 110;
               col3.HeaderStyle = style;
               col3.ElementStyle = style1;
               col3.Binding = new Binding("Reference");
               data.Columns.Add(col3);
               DataGridTextColumn col4 = new DataGridTextColumn();
               col4.Header = "# Iteration";
               col4.Width = 100;
               col4.HeaderStyle = style;
               col4.ElementStyle = style1;
               col4.Binding = new Binding("Iteration");
               data.Columns.Add(col4);
               DataGridTextColumn col5 = new DataGridTextColumn();
               col5.Header = "Spec";
               col5.Width = 100;
               col5.HeaderStyle = style;
               col5.ElementStyle = style1;
               data.Columns.Add(col5);
               col5.Binding = new Binding("Spec");
               st.Children.Add(txt);
               st.Children.Add(data);
             }                                    
            data.Items.Add(new Tool_Test() { Recipe_Name = dt[2].ToString(), Foup = dt[3].ToString(), Reference = dt[4].ToString(), Iteration = dt[5].ToString(), Spec = dt[6].ToString() });
        }
        last_tool_test = "";
      }
   }

edit: I think i found a solution by using resource:

<Window.Resources>
    <DataTemplate x:Key="CustomTemplate">
        <DataGrid x:Name="datagrid1" HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" SelectionMode="Extended" Margin="5,0,5,50" CanUserResizeColumns="False" AutoGenerateColumns="False" VerticalAlignment="Top" IsReadOnly="True" Width="750">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Sub Test Name" Width="*" Binding="{Binding Path=Recipe_Name}">
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="HorizontalAlignment" Value="Stretch"/>
                            <Setter Property="HorizontalContentAlignment" Value="Center"/>
                            <Setter Property="FontWeight"  Value="Bold" />
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="TextBlock">
                            <Setter Property="HorizontalAlignment" Value="Center" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
                <DataGridTextColumn Header="Spec" Width="*" Binding="{Binding Path=Foup}">
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="DataGridColumnHeader">
                            <Setter Property="HorizontalAlignment" Value="Stretch"/>
                            <Setter Property="HorizontalContentAlignment" Value="Center"/>
                            <Setter Property="FontWeight"  Value="Bold" />
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="TextBlock">
                            <Setter Property="HorizontalAlignment" Value="Center" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </DataTemplate>
</Window.Resources>

and in my code i added this:

data.RowDetailsTemplate = (DataTemplate)this.Resources["CustomTemplate"];

Now it's half working. I don't have experience with resource so i can't find a solution to Bind data to it. How can i do that?

Thank you for your help.

3
  • 1
    Why are you adding DataGridTextColumn using code behind (C#), a better and more efficient way would be to use XAML. Commented Jul 11, 2017 at 8:09
  • Because i'm creating Datagrid control for each element from my Database Commented Jul 11, 2017 at 8:31
  • @dadou even then, you should use databinding, and construct a datatemplate with the grid. Commented Jul 11, 2017 at 9:00

3 Answers 3

1

You could set the RowDetailsTemplate property to a DataTemplate that you create programmatically using the XamlReader class, e.g.:

string template = "<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x = \"http://schemas.microsoft.com/winfx/2006/xaml\"><TextBlock Text=\"some text...\"></DataTemplate>";
data.RowDetailsTemplate = XamlReader.Parse(template) as DataTemplate;
Sign up to request clarification or add additional context in comments.

Comments

1

I have built something along those lines a generic User Control that you can throw any ObservableCollection of objects at it and it will build the table, but you want to define the headers column widths etc. so it doesn't just use the function names for headers and default widths.

First I created an object to hold the settings for each column:

    public DataGridColumnSettings(string Header, int ColumnIndex, bool IsReadOnly = true, string Width = "100", bool ComboBoxColumn = false, bool CheckBoxColumn = false)
    {
        this.Header = Header;
        this.ColumnIndex = ColumnIndex;
        this.IsReadOnly = IsReadOnly;
        this.Width = Width;
        this.ComboBoxColumn = ComboBoxColumn;
        this.CheckBoxColumn = CheckBoxColumn;
    }

I then make a collection of these for each Model (I was using the MVVM pattern):

        public static Dictionary<string, DataGridColumnSettings> ColumnSettings
        {
            get { return new Dictionary<string, DataGridColumnSettings>() { { "PurchaseOrder", new DataGridColumnSettings("Order Number", 0) }, { "Width", new DataGridColumnSettings("Width", 1) }, { "Length", new DataGridColumnSettings("Length", 2) }, { "NumberOfPallets", new DataGridColumnSettings("No of Pallets", 3) }, { "BoardsPerStack", new DataGridColumnSettings("No of Boards", 4) }, { "NumberOfBoards", new DataGridColumnSettings("Total Boards", 5) } }; ; }
        }

The dictionary keys are the get set methods from the model for the required value in the table row (this is what the columns will be called by default)

and pass in this dictionary when creating the view object (UserControl) and store it inside the View:

 v_DataTable View = new v_DataTable(Model.ColumnSettings);

now add a handler for the data grids Auto Generating Column event:

<DataGrid AutoGeneratingColumn="dataGrid_AutoGeneratingColumn" /> (xaml)

and add the handler to the code behind:

private void dataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    string headername = e.Column.Header.ToString();

    //// Any column not in header details is a hidden column
    if (this.headerDetails.ContainsKey(headername))
    {
        Style centerStyle = new Style { TargetType = typeof(DataGridCell) };
        centerStyle.Setters.Add(new Setter(TextBlock.TextAlignmentProperty, TextAlignment.Center));
        Style headerCenterStyle = new Style { TargetType = typeof(DataGridColumnHeader) };
        headerCenterStyle.Setters.Add(new Setter(HorizontalContentAlignmentProperty, HorizontalAlignment.Center));


        try
        {
            e.Column.Width = Double.Parse(this.headerDetails[headername].Width);
        }
        catch(Exception ex)
        {
                e.Column.Width = 100;
        }

        // You can also add bindings here if required
        Binding headerTextBinding = new Binding();
        headerTextBinding.Source = this.headerDetails[headername];
        headerTextBinding.Path = new PropertyPath("Header");
        headerTextBinding.Mode = BindingMode.TwoWay;
        headerTextBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        BindingOperations.SetBinding(e.Column, DataGridTextColumn.HeaderProperty, headerTextBinding);


        e.Column.HeaderStyle = headerCenterStyle;
        e.Column.DisplayIndex = this.headerDetails[headername].ColumnIndex; //// If you have issues with the index been out of range, change the order of the get/set functions in the model class
        e.Column.CellStyle = centerStyle;                                   //// putting the get/set for any fields that are not displayed first will also help to avoid the issue
        e.Column.IsReadOnly = this.headerDetails[headername].IsReadOnly;
    }
    else
    {
        e.Column.Visibility = Visibility.Hidden;
    }
}

here you can use the settings you passed in to customise the columns as you require. (Should this be in the View Model if following MVVM pattern?)

Comments

0

I think i found a solution by using resource:

<Window.Resources>
<DataTemplate x:Key="CustomTemplate">
    <DataGrid x:Name="datagrid1" HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeRows="False" SelectionMode="Extended" Margin="5,0,5,50" CanUserResizeColumns="False" AutoGenerateColumns="False" VerticalAlignment="Top" IsReadOnly="True" Width="750">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Sub Test Name" Width="*" Binding="{Binding Path=Recipe_Name}">
                <DataGridTextColumn.HeaderStyle>
                    <Style TargetType="DataGridColumnHeader">
                        <Setter Property="HorizontalAlignment" Value="Stretch"/>
                        <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        <Setter Property="FontWeight"  Value="Bold" />
                    </Style>
                </DataGridTextColumn.HeaderStyle>
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="HorizontalAlignment" Value="Center" />
                    </Style>
                </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
            <DataGridTextColumn Header="Spec" Width="*" Binding="{Binding Path=Foup}">
                <DataGridTextColumn.HeaderStyle>
                    <Style TargetType="DataGridColumnHeader">
                        <Setter Property="HorizontalAlignment" Value="Stretch"/>
                        <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        <Setter Property="FontWeight"  Value="Bold" />
                    </Style>
                </DataGridTextColumn.HeaderStyle>
                <DataGridTextColumn.ElementStyle>
                    <Style TargetType="TextBlock">
                        <Setter Property="HorizontalAlignment" Value="Center" />
                    </Style>
                </DataGridTextColumn.ElementStyle>
            </DataGridTextColumn>
        </DataGrid.Columns>
    </DataGrid>
</DataTemplate>

and in my code i added this:

data.RowDetailsTemplate = (DataTemplate)this.Resources["CustomTemplate"];

Now it's half working. I don't have experience with resource so i can't find a solution to Bind data to it. How can i do that?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.