MSDN Documentation

Microsoft Developer Network

DataViews

This document provides a comprehensive overview of DataViews within ADO.NET, explaining their purpose, functionality, and usage for manipulating and presenting data.

Introduction to DataViews

A DataView object provides a way to create a custom view of the data contained within a DataTable. It allows you to filter, sort, and navigate the rows of a DataTable without actually modifying the underlying data itself. This is particularly useful when you need to display data in different ways for various UI controls, such as grids or dropdown lists.

Key features of DataView include:

  • Row Filtering: Select specific rows based on criteria.
  • Row Sorting: Order rows based on one or more columns.
  • Data Navigation: Move through the rows in the view.
  • Real-time Updates: Automatically reflects changes made to the underlying DataTable.

DataView objects are integral to data-bound controls in Windows Forms and ASP.NET, simplifying the process of presenting dynamic datasets.

Creating a DataView

To create a DataView, you first need a DataTable. You can then instantiate a DataView by passing the DataTable to its constructor. Optionally, you can specify initial filter and sort expressions.

C# Example: Basic DataView Creation


using System;
using System.Data;

public class DataViewExample
{
    public static void Main(string[] args)
    {
        // 1. Create a DataTable
        DataTable productsTable = new DataTable("Products");
        productsTable.Columns.Add("ProductID", typeof(int));
        productsTable.Columns.Add("ProductName", typeof(string));
        productsTable.Columns.Add("Category", typeof(string));
        productsTable.Columns.Add("Price", typeof(decimal));

        // Add some sample data
        productsTable.Rows.Add(1, "Laptop", "Electronics", 1200.00m);
        productsTable.Rows.Add(2, "Keyboard", "Electronics", 75.50m);
        productsTable.Rows.Add(3, "Desk Chair", "Furniture", 150.75m);
        productsTable.Rows.Add(4, "Monitor", "Electronics", 300.00m);
        productsTable.Rows.Add(5, "Office Desk", "Furniture", 450.00m);

        // 2. Create a DataView from the DataTable
        DataView productView = new DataView(productsTable);

        Console.WriteLine($"Initial number of rows in DataView: {productView.Count}");

        // You can now access data through productView
        foreach (DataRowView row in productView)
        {
            Console.WriteLine($"{row["ProductName"]} - {row["Category"]}");
        }
    }
}
                    

The DataView can be initialized with filter and sort expressions:

C# Example: Initializing with Filter and Sort


// Create a DataView for electronics, sorted by price ascending
DataView electronicsView = new DataView(productsTable, 
                                        "Category = 'Electronics'", 
                                        "Price ASC", 
                                        DataViewRowState.CurrentRows);

Console.WriteLine("\nElectronics sorted by price:");
foreach (DataRowView row in electronicsView)
{
    Console.WriteLine($"{row["ProductName"]} - ${row["Price"]}");
}
                    

Filtering and Sorting

The primary power of DataView lies in its ability to dynamically filter and sort data. These operations are performed using string expressions that resemble SQL WHERE and ORDER BY clauses.

Filtering

The RowFilter property is used to specify a filter expression. Only rows that match the criteria will be included in the view.

C# Example: Applying a Filter


// Filter for products with a price greater than $200
productView.RowFilter = "Price > 200";

Console.WriteLine($"\nNumber of products with Price > 200: {productView.Count}");
foreach (DataRowView row in productView)
{
    Console.WriteLine($"{row["ProductName"]} - ${row["Price"]}");
}

// Reset the filter
productView.RowFilter = ""; 
                    

Sorting

The SortProperty property is used to specify a sort expression. You can sort by one or more columns, in ascending (ASC) or descending (DESC) order.

C# Example: Applying Sorting


// Sort by Category, then by ProductName
productView.Sort = "Category ASC, ProductName ASC";

Console.WriteLine("\nAll products sorted by Category and Name:");
foreach (DataRowView row in productView)
{
    Console.WriteLine($"{row["Category"]} - {row["ProductName"]}");
}

// Sort by Price descending
productView.Sort = "Price DESC";
Console.WriteLine("\nAll products sorted by Price (Descending):");
foreach (DataRowView row in productView)
{
    Console.WriteLine($"{row["ProductName"]} - ${row["Price"]}");
}

// Reset the sort
productView.Sort = "";
                    
Note: Filter and sort expressions are case-sensitive by default if the underlying data is case-sensitive. For case-insensitive comparisons, you might need to use specific functions or properties depending on the data provider.

Using DataViewManager

The DataViewManager class is useful when you have a DataSet containing multiple related DataTable objects. It provides a default DataView for each table in the DataSet and manages them.

When you create a DataView using a DataViewManager, it can automatically apply default filter and sort settings based on relations defined within the DataSet.

C# Example: Using DataViewManager


// Assume 'myDataSet' is a DataSet containing multiple DataTables

// Create a DataSet (for demonstration purposes)
DataSet myDataSet = new DataSet();
DataTable customersTable = new DataTable("Customers");
customersTable.Columns.Add("CustomerID", typeof(int));
customersTable.Columns.Add("Name", typeof(string));
customersTable.Rows.Add(101, "Alice Smith");
customersTable.Rows.Add(102, "Bob Johnson");
myDataSet.Tables.Add(customersTable);

DataTable ordersTable = new DataTable("Orders");
ordersTable.Columns.Add("OrderID", typeof(int));
ordersTable.Columns.Add("CustomerID", typeof(int));
ordersTable.Columns.Add("OrderDate", typeof(DateTime));
ordersTable.Rows.Add(1001, 101, new DateTime(2023, 10, 26));
ordersTable.Rows.Add(1002, 101, new DateTime(2023, 11, 15));
ordersTable.Rows.Add(1003, 102, new DateTime(2023, 10, 30));
myDataSet.Tables.Add(ordersTable);

// Create a DataViewManager
DataViewManager dvManager = new DataViewManager(myDataSet);

// Get a DataView for the Customers table
DataView customerView = dvManager.CreateDataView(myDataSet.Tables["Customers"]);
Console.WriteLine($"\nCustomers from DataViewManager:");
foreach (DataRowView row in customerView)
{
    Console.WriteLine($"{row["Name"]}");
}

// Get a DataView for the Orders table
DataView orderView = dvManager.CreateDataView(myDataSet.Tables["Orders"]);
Console.WriteLine($"\nOrders from DataViewManager:");
foreach (DataRowView row in orderView)
{
    Console.WriteLine($"Order ID: {row["OrderID"]}, Customer ID: {row["CustomerID"]}");
}
                    

Advanced Scenarios

DataView Row States

DataView can display different states of rows from the underlying DataTable, such as:

  • DataViewRowState.CurrentRows: Only currently visible rows.
  • DataViewRowState.Added: Rows that have been added but not yet accepted changes.
  • DataViewRowState.Deleted: Rows marked for deletion.
  • DataViewRowState.ModifiedCurrent: Rows that have been modified and are currently visible.
  • DataViewRowState.ModifiedOriginal: The original version of rows that have been modified.
  • DataViewRowState.OriginalRows: All original rows (before any changes).

You can specify which row states to include in your DataView when filtering or sorting.

C# Example: Filtering Deleted Rows


// Assume productsTable has some deleted rows
// For example:
// productsTable.Rows[0].Delete(); 
// productsTable.AcceptChanges(); // This would remove them permanently. 
// If not accepted, they exist in OriginalRows and ModifiedOriginal states.

// To see rows that were deleted and are still in the system before AcceptChanges
// DataView deletedRowsView = new DataView(productsTable, 
//                                         "", 
//                                         "", 
//                                         DataViewRowState.Deleted);
// Console.WriteLine($"\nNumber of deleted rows: {deletedRowsView.Count}");
// Note: Accessing data from deleted rows requires accessing the 'OldValues' property of DataRowView.
                    

Using DataView with Data Binding

DataView is commonly used as a data source for UI controls. When a DataView is assigned to the DataSource property of a data-bound control (like a DataGridView in WinForms or a GridView in ASP.NET), the control automatically displays the data according to the DataView's current filter and sort settings.

Best Practices

  • Clear Filters and Sorts: When no longer needed, reset RowFilter and Sort properties to an empty string to improve performance and avoid unexpected behavior.
  • Use Efficient Expressions: Write filter and sort expressions that are as specific as possible to limit the data processed.
  • Handle DataViewRowState: Be mindful of the DataViewRowState you are querying, especially when dealing with data that has been modified or deleted.
  • DataViewManager for Datasets: Utilize DataViewManager when working with DataSet objects to easily manage views for multiple tables.
  • Avoid Redundant Views: If you only need one specific view of a DataTable, create a single DataView with appropriate filter and sort. If multiple views are needed, consider creating multiple DataView instances.