BeepBindingNavigator
Professional data record navigation and CRUD operations control with BindingSource integration for enterprise data applications
?? Table of Contents
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 | |
MessageButton |
Send message/email |
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
For large datasets, consider implementing virtual mode or paging to maintain responsive navigation performance.
Always handle the CurrentChanged event to update form state and ensure data consistency across bound controls.
Remember to call EndEdit() before saving data to ensure all pending changes are committed to the data source.