Overview

BeepBindingNavigator provides a comprehensive data navigation control for Windows Forms applications, offering complete CRUD (Create, Read, Update, Delete) operations through an intuitive toolbar interface. It seamlessly integrates with BindingSource and supports various data sources including DataTables, Lists, and custom data objects.

Built on the BeepControl foundation, BeepBindingNavigator features smart data source detection, automatic button state management, record position tracking, validation support, and comprehensive event handling. Perfect for data entry forms, administrative interfaces, and any application requiring professional data navigation capabilities.

Key Features

??? Data Source Flexibility

Support for DataTable, BindingSource, IList, IBindingList, and custom collections

?? Complete CRUD Operations

Built-in Create, Read, Update, Delete operations with validation and error handling

?? Smart Navigation

Previous/Next navigation with automatic button state management and position tracking

?? Event Propagation

Complete BindingSource event propagation for external component synchronization

?? Professional UI

Modern icon-based interface with tooltips, theme integration, and responsive layout

? Performance Optimized

Efficient data handling with minimal overhead and smart update mechanisms

Visual Preview

Data Navigation Interface

BeepBindingNavigator with integrated data form showing navigation and CRUD operations

Basic Usage

Simple Data Binding

// Create a BeepBindingNavigator
var navigator = new BeepBindingNavigator();
navigator.Dock = DockStyle.Top;
navigator.Height = 40;

// Create sample data
var customers = new List
{
    new Customer { Id = 1, Name = "John Doe", Email = "john@example.com" },
    new Customer { Id = 2, Name = "Jane Smith", Email = "jane@example.com" },
    new Customer { Id = 3, Name = "Bob Johnson", Email = "bob@example.com" }
};

// Bind data to navigator
navigator.DataSource = customers;

// Handle events
navigator.NewRecordCreated += (sender, bindingSource) =>
{
  //  Console.WriteLine("New record created");
};

navigator.SaveCalled += (sender, bindingSource) =>
{
  //  Console.WriteLine("Save operation requested");
    // Implement save logic here
};

navigator.DeleteCalled += (sender, bindingSource) =>
{
  //  Console.WriteLine("Delete operation requested");
    // Implement delete logic here
};

// Add to form
this.Controls.Add(navigator);

DataTable Integration

// Create and populate DataTable
var customersTable = new DataTable("Customers");
customersTable.Columns.Add("Id", typeof(int));
customersTable.Columns.Add("CompanyName", typeof(string));
customersTable.Columns.Add("ContactName", typeof(string));
customersTable.Columns.Add("Email", typeof(string));
customersTable.Columns.Add("Phone", typeof(string));
customersTable.Columns.Add("Status", typeof(string));

// Add sample data
customersTable.Rows.Add(1, "TechCorp Solutions", "John Smith", "john@techcorp.com", "+1-555-0123", "Active");
customersTable.Rows.Add(2, "DataSoft Inc", "Jane Wilson", "jane@datasoft.com", "+1-555-0124", "Active");
customersTable.Rows.Add(3, "CloudTech Ltd", "Mike Johnson", "mike@cloudtech.com", "+1-555-0125", "Inactive");

// Create binding navigator
var navigator = new BeepBindingNavigator
{
    DataSource = customersTable,
    Dock = DockStyle.Top,
    Height = 45,
    VerifyDelete = true // Show confirmation dialog before delete
};

// Handle data change events
navigator.CurrentChanged += (sender, e) =>
{
    RefreshFormControls();
};

navigator.ListChanged += (sender, e) =>
{
    switch (e.ListChangedType)
    {
        case ListChangedType.ItemAdded:
          //  Console.WriteLine($"New item added at index {e.NewIndex}");
            break;
        case ListChangedType.ItemDeleted:
          //  Console.WriteLine("Item deleted");
            break;
        case ListChangedType.ItemChanged:
          //  Console.WriteLine($"Item changed at index {e.NewIndex}");
            break;
    }
};

Properties

Core Properties

Property Type Default Description
DataSource object null Data source (DataTable, List, BindingSource, etc.)
BindingSource BindingSource New instance The underlying BindingSource for data operations
DMEEditor IDMEEditor null Data management editor for advanced operations
VerifyDelete bool true Show confirmation dialog before deleting records

Layout Properties

Property Type Default Description
ButtonBorderSize int 0 Border size for navigation buttons
ControlHeight int 30 Overall height of the navigator control

Button References

Button Function Icon
FindButton Trigger search functionality ?? Search
NewButton Add new record ? Plus
EditButton Edit current record ?? Pencil
SaveButton Save changes ? Check
RemoveButton Delete current record ? Minus
PreviousButton Navigate to previous record ?? Backwards
NextButton Navigate to next record ?? Forward
RollbackButton Cancel changes ? Go-back
PrinterButton Print current record ??? Print
MessageButton Send message/email ?? Mail

Events

Data Operation Events

Event Event Args Description
NewRecordCreated EventHandler<BindingSource> Fired when a new record is created
SaveCalled EventHandler<BindingSource> Fired when save operation is requested
DeleteCalled EventHandler<BindingSource> Fired when delete operation is requested
EditCalled EventHandler<BindingSource> Fired when edit operation is requested

Navigation Events

Event Event Args Description
CurrentChanged EventHandler Fired when current record changes
PositionChanged EventHandler Fired when record position changes
ListChanged EventHandler<ListChangedEventArgs> Fired when data list is modified
DataSourceChanged EventHandler Fired when data source is changed

Action Events

Event Event Args Description
ShowSearch EventHandler<BindingSource> Fired when search functionality is requested
CallPrinter EventHandler<BindingSource> Fired when print functionality is requested
SendMessage EventHandler<BindingSource> Fired when message/email functionality is requested

Examples

Complete Customer Management Form

public partial class CustomerForm : Form
{
    private BeepBindingNavigator navigator;
    private BeepTextBox txtCompanyName, txtContactName, txtEmail, txtPhone;
    private BeepComboBox cmbStatus;
    private BeepLabel lblCustomerId;
    private List customers;
    private bool isEditing = false;

    public CustomerForm()
    {
        InitializeComponent();
        SetupNavigator();
        SetupForm();
        LoadData();
    }

    private void SetupNavigator()
    {
        navigator = new BeepBindingNavigator
        {
            Dock = DockStyle.Top,
            Height = 45,
            VerifyDelete = true
        };

        // Wire up events
        navigator.NewRecordCreated += Navigator_NewRecordCreated;
        navigator.SaveCalled += Navigator_SaveCalled;
        navigator.DeleteCalled += Navigator_DeleteCalled;
        navigator.EditCalled += Navigator_EditCalled;
        navigator.CurrentChanged += Navigator_CurrentChanged;
        navigator.ShowSearch += Navigator_ShowSearch;
        navigator.CallPrinter += Navigator_CallPrinter;

        this.Controls.Add(navigator);
    }

    private void SetupForm()
    {
        var mainPanel = new BeepPanel
        {
            Dock = DockStyle.Fill,
            Padding = new Padding(20)
        };

        var formLayout = new TableLayoutPanel
        {
            Dock = DockStyle.Fill,
            ColumnCount = 2,
            RowCount = 6,
            AutoSize = true
        };

        // Setup form controls
        lblCustomerId = new BeepLabel { Text = "Customer ID:", AutoSize = true };
        var txtCustomerId = new BeepTextBox { ReadOnly = true, Width = 200 };

        formLayout.Controls.Add(lblCustomerId, 0, 0);
        formLayout.Controls.Add(txtCustomerId, 1, 0);

        formLayout.Controls.Add(new BeepLabel { Text = "Company Name:", AutoSize = true }, 0, 1);
        txtCompanyName = new BeepTextBox { Width = 300 };
        formLayout.Controls.Add(txtCompanyName, 1, 1);

        formLayout.Controls.Add(new BeepLabel { Text = "Contact Name:", AutoSize = true }, 0, 2);
        txtContactName = new BeepTextBox { Width = 300 };
        formLayout.Controls.Add(txtContactName, 1, 2);

        formLayout.Controls.Add(new BeepLabel { Text = "Email:", AutoSize = true }, 0, 3);
        txtEmail = new BeepTextBox { Width = 300 };
        formLayout.Controls.Add(txtEmail, 1, 3);

        formLayout.Controls.Add(new BeepLabel { Text = "Phone:", AutoSize = true }, 0, 4);
        txtPhone = new BeepTextBox { Width = 200 };
        formLayout.Controls.Add(txtPhone, 1, 4);

        formLayout.Controls.Add(new BeepLabel { Text = "Status:", AutoSize = true }, 0, 5);
        cmbStatus = new BeepComboBox { Width = 150 };
        cmbStatus.Items.AddRange(new[] { "Active", "Inactive", "Pending" });
        formLayout.Controls.Add(cmbStatus, 1, 5);

        // Bind controls to data source
        txtCustomerId.DataBindings.Add("Text", navigator.BindingSource, "Id");
        txtCompanyName.DataBindings.Add("Text", navigator.BindingSource, "CompanyName");
        txtContactName.DataBindings.Add("Text", navigator.BindingSource, "ContactName");
        txtEmail.DataBindings.Add("Text", navigator.BindingSource, "Email");
        txtPhone.DataBindings.Add("Text", navigator.BindingSource, "Phone");
        cmbStatus.DataBindings.Add("Text", navigator.BindingSource, "Status");

        mainPanel.Controls.Add(formLayout);
        this.Controls.Add(mainPanel);
    }

    private void LoadData()
    {
        // Simulate loading data from database
        customers = new List
        {
            new Customer 
            { 
                Id = 1, 
                CompanyName = "TechCorp Solutions", 
                ContactName = "John Smith", 
                Email = "john@techcorp.com", 
                Phone = "+1-555-0123", 
                Status = "Active" 
            },
            new Customer 
            { 
                Id = 2, 
                CompanyName = "DataSoft Inc", 
                ContactName = "Jane Wilson", 
                Email = "jane@datasoft.com", 
                Phone = "+1-555-0124", 
                Status = "Active" 
            },
            new Customer 
            { 
                Id = 3, 
                CompanyName = "CloudTech Ltd", 
                ContactName = "Mike Johnson", 
                Email = "mike@cloudtech.com", 
                Phone = "+1-555-0125", 
                Status = "Inactive" 
            }
        };

        navigator.DataSource = customers;
    }

    private void Navigator_NewRecordCreated(object sender, BindingSource bindingSource)
    {
        isEditing = true;
        EnableFormEditing(true);
        
        // Set default values for new record
        if (bindingSource.Current is Customer customer)
        {
            customer.Id = GetNextCustomerId();
            customer.Status = "Active";
        }
    }

    private void Navigator_SaveCalled(object sender, BindingSource bindingSource)
    {
        try
        {
            if (ValidateForm())
            {
                // Simulate saving to database
                SaveToDatabase();
                isEditing = false;
                EnableFormEditing(false);
                MessageBox.Show("Customer saved successfully!", "Success", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"Error saving customer: {ex.Message}", "Error", 
                MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    private void Navigator_DeleteCalled(object sender, BindingSource bindingSource)
    {
        try
        {
            if (bindingSource.Current is Customer customer)
            {
                // Simulate database deletion
                DeleteFromDatabase(customer.Id);
                MessageBox.Show("Customer deleted successfully!", "Success", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"Error deleting customer: {ex.Message}", "Error", 
                MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    private void Navigator_EditCalled(object sender, BindingSource bindingSource)
    {
        isEditing = true;
        EnableFormEditing(true);
    }

    private void Navigator_CurrentChanged(object sender, EventArgs e)
    {
        // Update form when current record changes
        if (!isEditing)
        {
            EnableFormEditing(false);
        }
        UpdateFormState();
    }

    private void Navigator_ShowSearch(object sender, BindingSource bindingSource)
    {
        var searchForm = new CustomerSearchForm(customers);
        if (searchForm.ShowDialog() == DialogResult.OK)
        {
            var selectedCustomer = searchForm.SelectedCustomer;
            var index = customers.IndexOf(selectedCustomer);
            if (index >= 0)
            {
                bindingSource.Position = index;
            }
        }
    }

    private void Navigator_CallPrinter(object sender, BindingSource bindingSource)
    {
        if (bindingSource.Current is Customer customer)
        {
            PrintCustomerReport(customer);
        }
    }

    private bool ValidateForm()
    {
        var errors = new List();

        if (string.IsNullOrWhiteSpace(txtCompanyName.Text))
            errors.Add("Company Name is required");

        if (string.IsNullOrWhiteSpace(txtContactName.Text))
            errors.Add("Contact Name is required");

        if (string.IsNullOrWhiteSpace(txtEmail.Text))
            errors.Add("Email is required");
        else if (!IsValidEmail(txtEmail.Text))
            errors.Add("Invalid email format");

        if (errors.Any())
        {
            MessageBox.Show(string.Join("\n", errors), "Validation Error", 
                MessageBoxButtons.OK, MessageBoxIcon.Warning);
            return false;
        }

        return true;
    }

    private void EnableFormEditing(bool enabled)
    {
        txtCompanyName.ReadOnly = !enabled;
        txtContactName.ReadOnly = !enabled;
        txtEmail.ReadOnly = !enabled;
        txtPhone.ReadOnly = !enabled;
        cmbStatus.Enabled = enabled;
    }

    private void UpdateFormState()
    {
        // Update form state based on current record
        var hasData = navigator.BindingSource.Current != null;
        // Enable/disable controls based on data availability
    }

    // Helper methods
    private int GetNextCustomerId() => customers.Max(c => c.Id) + 1;
    private void SaveToDatabase() { /* Database save logic */ }
    private void DeleteFromDatabase(int customerId) { /* Database delete logic */ }
    private void PrintCustomerReport(Customer customer) { /* Print logic */ }
    private bool IsValidEmail(string email) => email.Contains("@") && email.Contains(".");
}

public class Customer
{
    public int Id { get; set; }
    public string CompanyName { get; set; }
    public string ContactName { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public string Status { get; set; }
}

Theming

BeepBindingNavigator provides comprehensive theming with automatic application to all child controls:

Theme Application

var navigator = new BeepBindingNavigator
{
    Theme = "DarkTheme",
    DataSource = myDataSource
};

// Theme automatically applies to:
// - All navigation buttons
// - Record number label
// - Button hover states
// - Tooltip styling
// - Background colors

// Manual theme refresh
navigator.ApplyTheme();

Navigator-Specific Theme Properties

  • PanelBackColor - Main navigator background
  • ButtonBackColor - Navigation button backgrounds
  • ButtonForeColor - Button icon colors
  • ButtonHoverBackColor - Button hover states
  • LabelBackColor - Record counter background
  • LabelForeColor - Record counter text
  • ToolTipBackColor/ForeColor - Tooltip styling

Best Practices

??? Data Management

  • Data validation: Always validate data before saving operations
  • Error handling: Implement comprehensive error handling for all CRUD operations
  • Transaction support: Use database transactions for complex operations
  • Dirty checking: Track form changes to prevent data loss

?? User Experience

  • Confirmation dialogs: Use VerifyDelete for important delete operations
  • Visual feedback: Provide clear feedback for all operations
  • Form state management: Properly enable/disable controls based on edit mode
  • Keyboard shortcuts: Support standard keyboard navigation

? Performance

  • Lazy loading: Load data only when needed for large datasets
  • Paging: Implement paging for very large data sources
  • Efficient binding: Use appropriate data binding strategies
  • Memory management: Properly dispose of large data objects

?? Implementation

  • Event handling: Handle all relevant navigator events for complete functionality
  • Data source flexibility: Support multiple data source types
  • Search integration: Implement search functionality through ShowSearch event
  • Print support: Provide meaningful print functionality
?? Performance Tip

For large datasets, consider implementing virtual mode or paging to maintain responsive navigation performance.

? Best Practice

Always handle the CurrentChanged event to update form state and ensure data consistency across bound controls.

?? Data Warning

Remember to call EndEdit() before saving data to ensure all pending changes are committed to the data source.