locked
Create DataGrid.Columns from code behind using WPF RRS feed

  • Question

  • Hi everyone,

    I have a DataGrid where I am creating 2 columns(Delete and Edit) in xaml like this

    <DataGrid Height="226" HorizontalAlignment="Left" Margin="106,111,0,0" Name="DgEmp" VerticalAlignment="Top" Width="684" ColumnWidth="*" CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Actions">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Button Content="Delete" Name="BtnDelete" Click="btnDelete_Click"/>
                            <Button Content="Edit" x:Name="BtnEdit" Click="btnEdit_Click"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

    I want to create this from code behind with some blank space between them so that it will look good.

    Also I am facing some issue on delete and Edit.

    I have bind my grid like this( Auto generated columns is true for the datagridview)

     private void GridBind()
            {
                try
                {
                    using (var con = new SqlConnection(_conString))
                    {
                        const string sqlqry = "select ROW_NUMBER() OVER (ORDER BY EmpNo) AS [SlNo],EmpNo,EmpName,Salary,DeptNo from dbo.Employee";
                        var cmd = new SqlCommand(sqlqry, con);
                        _adapt = new SqlDataAdapter(cmd);
                        var dt = new DataTable("Employee");
                        _adapt.Fill(dt);
                        DgEmp.ItemsSource = dt.DefaultView;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Some error encountered" + ex.Message);
                }
            }

    My Button Delete event is like this

    private void btnDelete_Click(object sender, RoutedEventArgs e)
    {
       //What should be the Code to get the details of the clicked employee so that I can delete the particular row
    }

    And also how I will bind my DataGrid if My .xalm code is like this

    <DataGrid Height="226" HorizontalAlignment="Left" Margin="106,111,0,0" Name="DgEmp" VerticalAlignment="Top" Width="684" ColumnWidth="*" CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="SL No" Width="*"/> 
            <DataGridTextColumn Header="Emp No" Width="*"/>
            <DataGridTextColumn Header="Emp Name" Width="*" />
            <DataGridTextColumn Header="Salary" Width="*" />
            <DataGridTextColumn Header="Dept No" Width="*" />
            <DataGridTemplateColumn Header="Actions">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <Button Content="Delete" Name="BtnDelete" Click="btnDelete_Click"/>
                            <Button Content="Edit" x:Name="BtnEdit" Click="btnEdit_Click"/>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

    I am not using MVVM concept here.

    I know I have asked too many questions here. Because I am facing too many confusion while binding WPF Grid.

    Please help me.

    Thanks 


    M.Sabyasachi

    Monday, August 3, 2015 10:22 AM

Answers

  • Please only ask one question per thread. Start another thread if you have another question.

    >>I want to create this from code behind with some blank space between them so that it will look good.

    This is how you could create a DataGridTemplateColumn programmatically:

    DataGridTemplateColumn col = new DataGridTemplateColumn();
                col.Header = "Actions";
                DataTemplate dt = new DataTemplate();
                var sp = new FrameworkElementFactory(typeof(StackPanel));
                sp.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
                
                var btn1 = new FrameworkElementFactory(typeof(Button));
                btn1.SetValue(Button.ContentProperty, "Delete");
                btn1.AddHandler(Button.ClickEvent, new RoutedEventHandler(btnDelete_Click));
                 btn1.SetValue(Button.MarginProperty, new Thickness(0, 0, 10, 0));
                sp.AppendChild(btn1);
    
                var btn2 = new FrameworkElementFactory(typeof(Button));
                btn2.SetValue(Button.ContentProperty, "Edit");
                btn2.AddHandler(Button.ClickEvent, new RoutedEventHandler(btnEdit_Click));
                sp.AppendChild(btn2);
    
                dt.VisualTree = sp;
                col.CellTemplate = dt;
    
                DgEmp.Columns.Add(col);
    

    Adding space between the Buttons is just a matter of setting the Margin property of either of them as shown above.

    >>What should be the Code to get the details of the clicked employee so that I can delete the particular row

    You could cast the SelectedItem to a DataRowView and call the Row.Delete() method:

            private void btnDelete_Click(object sender, RoutedEventArgs e)
            {
                DataRowView drv = DgEmp.SelectedItem as DataRowView;
                if (drv != null)
                {
                    drv.Row.Delete();
                }
            }


    >>And also how I will bind my DataGrid if My .xalm code is like this

    You need to specify the name of the column in the source DataView to bind to for each of the DataGridTextColumns ("SlNo" is the name of the column in the below sample markup):

    <DataGridTextColumn Header="SL No" Width="*" Binding="{Binding SlNo}"/>

    Hope that helps.

    Please rememeber to mark to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    • Proposed as answer by Xavier Xie-MSFT Tuesday, August 4, 2015 8:11 AM
    • Marked as answer by Sabyasachi.M Tuesday, August 4, 2015 5:33 PM
    Monday, August 3, 2015 2:05 PM
  • >>So how can I bind this using my given Xaml.

    Exactly as I showed you:

    <DataGridTextColumn Header="SL No" Width="*" Binding="{Binding SlNo}"/>
    <DataGridTextColumn Header="Salary" Width="*" Binding="{Binding Salary}"/>

    You are not binding to the database but to the DataView of a DataTable in memory.

    You probably want to make both these fields, or at least the SlNo field, non-editable in the DataGrid by setting the IsReadOnly property to true:

    <DataGridTextColumn Header="SL No" Width="*" Binding="{Binding SlNo}" IsReadOnly="True"/>


    Hope that helps.

    Please rememeber to close your threads by marking all helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Tuesday, August 4, 2015 1:51 PM

All replies

  • Please only ask one question per thread. Start another thread if you have another question.

    >>I want to create this from code behind with some blank space between them so that it will look good.

    This is how you could create a DataGridTemplateColumn programmatically:

    DataGridTemplateColumn col = new DataGridTemplateColumn();
                col.Header = "Actions";
                DataTemplate dt = new DataTemplate();
                var sp = new FrameworkElementFactory(typeof(StackPanel));
                sp.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
                
                var btn1 = new FrameworkElementFactory(typeof(Button));
                btn1.SetValue(Button.ContentProperty, "Delete");
                btn1.AddHandler(Button.ClickEvent, new RoutedEventHandler(btnDelete_Click));
                 btn1.SetValue(Button.MarginProperty, new Thickness(0, 0, 10, 0));
                sp.AppendChild(btn1);
    
                var btn2 = new FrameworkElementFactory(typeof(Button));
                btn2.SetValue(Button.ContentProperty, "Edit");
                btn2.AddHandler(Button.ClickEvent, new RoutedEventHandler(btnEdit_Click));
                sp.AppendChild(btn2);
    
                dt.VisualTree = sp;
                col.CellTemplate = dt;
    
                DgEmp.Columns.Add(col);
    

    Adding space between the Buttons is just a matter of setting the Margin property of either of them as shown above.

    >>What should be the Code to get the details of the clicked employee so that I can delete the particular row

    You could cast the SelectedItem to a DataRowView and call the Row.Delete() method:

            private void btnDelete_Click(object sender, RoutedEventArgs e)
            {
                DataRowView drv = DgEmp.SelectedItem as DataRowView;
                if (drv != null)
                {
                    drv.Row.Delete();
                }
            }


    >>And also how I will bind my DataGrid if My .xalm code is like this

    You need to specify the name of the column in the source DataView to bind to for each of the DataGridTextColumns ("SlNo" is the name of the column in the below sample markup):

    <DataGridTextColumn Header="SL No" Width="*" Binding="{Binding SlNo}"/>

    Hope that helps.

    Please rememeber to mark to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    • Proposed as answer by Xavier Xie-MSFT Tuesday, August 4, 2015 8:11 AM
    • Marked as answer by Sabyasachi.M Tuesday, August 4, 2015 5:33 PM
    Monday, August 3, 2015 2:05 PM
  • Creating Grid.columns worked well thanks.

    But as per the last answer I am generating SlNo like this(there is no column for database in SLNo) and also I do some of the calculation for Salary like this

    Select ROW_NUMBER() OVER (ORDER BY EmpNo) AS [SlNo], Empno, EmpName, (Salary+(0.5*Salary)) as Salary,

    Salary as [Basic Salary], DeptNo from Employee

    So how can I bind this using my given Xaml.

    Sorry for asking so many question in same thread


    M.Sabyasachi

    Tuesday, August 4, 2015 5:28 AM
  • >>So how can I bind this using my given Xaml.

    Exactly as I showed you:

    <DataGridTextColumn Header="SL No" Width="*" Binding="{Binding SlNo}"/>
    <DataGridTextColumn Header="Salary" Width="*" Binding="{Binding Salary}"/>

    You are not binding to the database but to the DataView of a DataTable in memory.

    You probably want to make both these fields, or at least the SlNo field, non-editable in the DataGrid by setting the IsReadOnly property to true:

    <DataGridTextColumn Header="SL No" Width="*" Binding="{Binding SlNo}" IsReadOnly="True"/>


    Hope that helps.

    Please rememeber to close your threads by marking all helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Tuesday, August 4, 2015 1:51 PM