Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add Button to ListView dynamically in each row using C#

Tags:

c#

listview

wpf

I have a ListView in which I have to show all rows fetched from my database table. Again I have to give two edit and delete buttons in each row. As I am beginner for the same, I tried the following code in XAML-

<ListView Height="352" HorizontalAlignment="Left" Margin="20,90,0,0" Name="Tab1lstProductCategories" VerticalAlignment="Top" Width="1008">
                        <ListView.View>
                            <GridView>
                                <GridViewColumn Header="Category Name" DisplayMemberBinding="{Binding Col1}" Width="200"/>
                                <GridViewColumn Header="Created Date" DisplayMemberBinding="{Binding Col2}" Width="200"/>
                                <GridViewColumn Header="Last Updated" DisplayMemberBinding="{Binding Col3}" Width="200"/>
                                <GridViewColumn Header="Edit" Width="200">
                                    <GridViewColumn.CellTemplate>
                                        <DataTemplate>
                                            <Button Content="Edit" Click="EditCategory" CommandParameter="{Binding Id}"/>
                                        </DataTemplate>
                                    </GridViewColumn.CellTemplate>
                                </GridViewColumn>
                                <GridViewColumn Header="Delete" Width="200">
                                    <GridViewColumn.CellTemplate>
                                        <DataTemplate>
                                            <Button Content="Delete" Click="DeleteCategory"/>
                                        </DataTemplate>
                                    </GridViewColumn.CellTemplate>
                                </GridViewColumn>
                            </GridView>
                        </ListView.View>
                    </ListView>

And in C# I Wrote-

 DataTable dt=db.Select("select * from ProductCategories");
           for (int i = 0; i < dt.Rows.Count; i++)
        {
            //Button edit, delete;
            //edit = new Button();
            //edit.Content="Edit";
            //edit.Click += EditCategory;
            //delete= new Button();
            //delete.Content="Delete";
            //delete.Click += DeleteCategory;
            //edit.CommandParameter = dt.Rows[i]["Id"];
            //delete.CommandParameter = dt.Rows[i]["Id"];
            Tab1lstProductCategories.Items.Add(new { Col1 = dt.Rows[i]["CategoryName"], Col2 = dt.Rows[i]["CreatedDate"], Col3=dt.Rows[i]["LastUpdated"]});                
        }



private void EditCategory(object sender, RoutedEventArgs e)
        {
            Button b=sender as Button;
            MessageBox.Show(b.CommandParameter.ToString());
        }

    private void DeleteCategory(object sender, RoutedEventArgs e)
    {
    }

I got the result as- enter image description here

I want button over there, Please help me out.

like image 790
Prateek Shukla Avatar asked Oct 14 '13 13:10

Prateek Shukla


1 Answers

Ok, so I see a couple of issues with your code.

1) You really should create a proper datatype like @HighCore suggested. Looking at your code I assume it will look something like this:

public class ProductCategory
{
    public int Id { get; set; }

    public string CategoryName { get; set; }

    public DateTime CreatedDate { get; set; }

    public DateTime LastUpdated { get; set; }
}

Then create a collection of ProductCategory instead of directly adding anonymous types

DataTable dt=db.Select("select * from ProductCategories");

// Create a collection for your types
ObservableCollection<ProductCategory> list = new ObservableCollection<ProductCategory>();

for (int i = 0; i < dt.Rows.Count; i++)
{
    ProductCategory productCategory = new ProductCategory
    {
        // Casting might be needed here depending on your data types ...
        Id = dt.Rows[i]["Id"],
        CategoryName = dt.Rows[i]["CategoryName"],
        CreatedDate = dt.Rows[i]["CreatedDate"],
        LastUpdated = dt.Rows[i]["LastUpdated"]
    };

    list.Add(productCategory);
}

2) You are directly adding item's to the ListView which is wrong. What you should be doing is set your collection to be the ItemsSource of your ListView.

Tab1lstProductCategories.ItemsSource = list;

3) After using CellTemplate to achieve the ListView wanted look through xaml and changing the DisplayMemberBinding binding to the appropriate properties, you can bind the CommandParameter through the default {Binding} expression which will set the command parameter to be the ProductCategory item it represents.

    <ListView Height="352" HorizontalAlignment="Left" Margin="20,90,0,0" Name="Tab1lstProductCategories" VerticalAlignment="Top" Width="1008">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Category Name" DisplayMemberBinding="{Binding CategoryName}" Width="200"/>
                <GridViewColumn Header="Created Date" DisplayMemberBinding="{Binding CreatedDate}" Width="200"/>
                <GridViewColumn Header="Last Updated" DisplayMemberBinding="{Binding LastUpdated}" Width="200"/>
                <GridViewColumn Header="Edit" Width="200">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="Edit" Click="EditCategory" CommandParameter="{Binding}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="Delete" Width="200">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="Delete" Click="DeleteCategory" CommandParameter="{Binding}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>

From the event handlers - EditCategory and DeleteCategory, you can extract the Id of the ProductCategory

private void EditCategory(object sender, RoutedEventArgs e)
{
    Button b=sender as Button;
    ProductCategory productCategory = b.CommandParameter as ProductCategory;
    MessageBox.Show(productCategory.Id);
}

This should be sufficient to make your code work, but there are several other points I'd like to make

a. You should highly consider using MVVM pattern. this will mean not using event handlers in code behind but using Commands instead, and use CommandParameter the way it was originally intended to be used.

b. Consider some ORM framework instead of binding the database directly to your UI. this create incredibly tight coupling which will make your code a lot less reusable, and flexible.

Hope this helps

like image 88
Omri Btian Avatar answered Sep 30 '22 04:09

Omri Btian