Kamal
Kamal

Reputation: 477

Datagrid in WPF C#. How to add custom values to each cells in a row

I have three textboxes. I need to add each value to the corresponding fields. Datagrid have headers "#, ProductName, ProductCode, Tax, Total"

WPF

                <DataGrid ItemsSource="{Binding dt}" x:Name="dgrdBilling" MinColumnWidth="100" Grid.Row="1" CanUserReorderColumns="False" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="Cell" Margin="1,0,-1,0">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="#" Width="25" CanUserResize="False" MinWidth="25"/>
                        <DataGridTextColumn Header="Name"/>
                        <!--<DataGridTextColumn Header="Name" Binding="{Binding Path=ProductName}"/>-->
                        <DataGridTextColumn Header="Code"/>
                        <DataGridTextColumn Header="Quantity"/>
                        <DataGridTextColumn Header="Price"/>
                        <DataGridTextColumn Header="Tax1"/>
                        <DataGridTextColumn Header="Tax2"/>
                        <DataGridTextColumn Header="Tax3"/>
                        <DataGridTextColumn Header="Total"/>
                    </DataGrid.Columns>
                </DataGrid>

Click Event of button to add data to datagrid

    private void btnAddProduct_Click(object sender, RoutedEventArgs e)
    {
        SqlCeCommand com = new SqlCeCommand("SELECT * FROM Products_Master WHERE ProductName =('" + txtAutoProductName.Text + "') OR ProductCode = ('" + txtProductCode.Text + "')", con);
        try
        {
            System.Windows.Controls.DataGrid dg = new System.Windows.Controls.DataGrid();
            SqlCeDataAdapter da = new SqlCeDataAdapter();
            BindingSource bSource = new BindingSource();
            DataTable dt = new DataTable();
            DataRow newRow = dt.NewRow();
            da.SelectCommand = com;
            da.Fill(dt);
            bSource.DataSource = dt;
            dg.Items.Add(txtAutoProductName.Text);
            dg.Items.Add(txtAutoProductCode.Text);
            dg.Items.Add(txtQuantity.Text);
            //dgrdBilling.ItemsSource = dt.DefaultView;
            //dgrdBilling.Items.Add(dg);
            da.Update(dt);
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message, System.Windows.Forms.Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

Upvotes: 1

Views: 5468

Answers (2)

Omri Btian
Omri Btian

Reputation: 6547

Seem like you confused a lot of stuff here.

First of all, you shouldn't manipulate UI Elements from code-behind in WPF. You should have a proper data type containing the ProductName, ProductCode, Tax, Total or any other fields you may want, fill a collection of that type, and bind THAT to the DataGrid.

public class Product
{
    public string ProductName { get; set; }

    public string ProductCode { get; set; }

    public int Tax { get; set; }

    public int Total { get; set; }
}

Store a collection of that class (preferably ObservableCollection that notifys the UI when it changes to make it update itself)

public ObservableCollection<Product> Products { get; set;}

Usually it should be done in different class that you set as the DataContext of the window (Known as ViewModel), But if you set it in the code-behind, you can just set the window's DataContext to itself. In window's constructor after InitializeComponents() add

DataContext = this

Now, create a Product with the relevant data and add it to the collection instead of directly to the grid:

        Product p = new Product
        {
            ProductName = txtAutoProductName.Text,
            ProductCode = txtAutoProductCode.Text
            // Fill in the rest of the properties as you want ...
        }
        Products.Add(p);

Finally, Alter your grid to look something like this:

<DataGrid ItemsSource="{Binding Products}" x:Name="dgrdBilling" MinColumnWidth="100" Grid.Row="1" CanUserReorderColumns="False" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="Cell" Margin="1,0,-1,0">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="#" Width="25" CanUserResize="False" MinWidth="25"/>
                    <DataGridTextColumn Header="Name" Binding="{Binding ProductName}"/>
                    <DataGridTextColumn Header="Code" Binding="{Binding ProductCode}"/>
                    <!-- rest of your columns ... -->
                </DataGrid.Columns>
            </DataGrid>

To are some links that can help you understand the concept better:

Transitioning from Windows Forms to WPF

http://www.codeproject.com/Articles/140621/WPF-Tutorial-Concept-Binding

Also you should look into the MVVM pattern which is considered the best practice when developing WPF application

Good luck

Upvotes: 2

Dennis
Dennis

Reputation: 37770

You're misunderstanding bindings in WPF and mixing WinForms and WPF binding approach.

First of all, DataGrid supports direct binding to a DataTable instance, so, it is enough to set DataGrid.ItemsSource to a DataTable:

<DataGrid ItemsSource="{Binding SomDataTable}">

The second, DataGrid by default can generate columns from DataTable schema. If you want to override this behavior, you should turn off column generation (this is done in your code), and, also, you should bind your columns with DataTable columns like this:

<DataGridTextColumn Header="MyHeader" Binding="{Binding MyDataTableColumnName}"/>

The third, you don't want to add a row to the DataGrid. You want to a row to the DataTable, so, your click handler should look like this:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // ...
        dataTable.Rows.Add(/* ... */);
    }

Upvotes: 1

Related Questions