Tự viết ứng dụng quản lý xe ra vào C# Winforms và Firebase

Trong bài viết này Kiso chia sẽ cho các bạn một ứng dụng khá thú vị đó là ứng dụng quản lý xe ra vào C# Winforms và Firebase. Đây là một ứng dụng quản lý các thông tin về chủ xe cũng như thời gian ra vào bãi đỗ xe.

Ứng dụng sử dụng Firebase Realtime Database để làm cở sở dữ liệu và C# Winforms làm ngôn ngữ lập trình. Nào chúng ta bắt đầu viết thôi nhé !!!

Mô tả ứng dụng quản lý xe ra vào C# Winforms và Firebase

Chúng ta sẽ thực hiện một ứng dụng quản lý xe ra vào với cơ sở dữ liệu Firebase như hình dưới đây.

parking 01 png

Mô tả Realtime Database Firebase

Bài viết này được đăng tại [kiso.vn]

  • “Quản lý xe” bao gồm các thông tin: Họ tên, biển số xe, …
  • “Count” quản lý tổng số xe đã ra vào đỗ xe.

parking 02 png

Mô tả ứng dụng

  • Sử dụng Firebase làm cơ sở dữ liệu cho ứng dụng.
  • Hiển thị danh sách các xe trên DataGridView bao gồm các thông tin: Họ tên, Biển số xe, Số điện thoại, Thời gian vào, Thời gian ra, ….
  • Hiển thị tổng các xe đã đỗ tại bãi.
  • Chức năng Biding, khi người dùng nhấn vào xe bất kỳ trên DataGridView thì các thông tin của xe đó sẽ được hiển thị trên các TextBox tương ứng.
  • Chức năng thêm mới khi người dùng nhập đầy đủ thông tin và nhấn Button “Thêm”.
  • Chức năng sửa thông tin.
  • Chức năng xóa, hiển thị thông báo yêu cầu người dùng xác nhận trước khi xóa.
  • Tìm kiếm theo biển số xe.
  • Chức năng xuất danh sách ra Excel.
  • Khi bắt đầu chạy chương trình sẽ hiện thị danh sách các xe. Sau khi thực hiện các chức năng thêm, sửa, xóa sẽ cập nhật lại danh sách xe trên DataGridView.

Thiết kế giao diện cho ứng dụng

Ở phần này mình sẽ thực hiện thiết kế giao diện như hình dưới đây, các bạn có thể tự thiết kế cho mình một giao diện tùy thích nhé.

parking 03 png

Như các bạn thấy thì ở đây có:

  • Các Button tương ứng với các chức năng ở phần mô tả.
  • Các TextBox và DateTimePicker để quản lý các thông tin của xe.
  • DataGridView để hiển thị danh sách các xe ra vào.

*Lưu ý: Ngoài ra cần thêm một control SaveFileDialog để chọn vị trí lưu file Excel đã Export.

Kết nối C# Winforms với Firebase Realtime Database

Việc đầu tiên chúng ta cần kết nối từ C# Winforms với Realtime Database trên Firebase để có thể thực hiện các thao tác với dữ liệu. Mình đã có viết một bài hướng dẫn cách kết nối C# Winforms với Firebase, các bạn có thể xem lại đễ hiểu rõ hơn nhé.

IFirebaseConfig config = new FirebaseConfig
{
      AuthSecret = "opvPdDshiA5ZWttVVilmsxJPJWeuIndiNuUkL3H2",
     BasePath = "https://managementstudent-8d677-default-rtdb.firebaseio.com/"
};
  
IFirebaseClient client;
  
private void Form1_Load(object sender, EventArgs e)
{
     client = new FireSharp.FirebaseClient(config);
}

Xử lý chức năng cho ứng dụng

Sau khi đã tạo giao diện và thực hiện kết nối C# Winforms với Realtime Database trên Firebase, ta bắt đầu xử lý các sự kiện. Mình sẽ thực hiện lần lượt từng chức năng như phần mô tả ứng dụng ở ban đầu.

Hiển thị danh sách xe ra vào

Để hiển thị được danh sách xe ra vào, chúng ta sẽ thực hiện theo từng bước sau.

Bước 1: Tạo hàm RetriveCar() để lấy danh sách các xe trên Firebase đổ vào DataGridView.

private async void RetriveCar()
{
    dt.Rows.Clear();
    int i = 0;
    FirebaseResponse resp1 = await client.GetTaskAsync("Count");
    Count obj1 = resp1.ResultAs<Count>();

    int cnt = Convert.ToInt32(obj1.cnt);

    while (true)
    {
        if (i == cnt)
        {
            break;
        }
        i++;
        try
        {
            FirebaseResponse resp2 = await client.GetTaskAsync("QuanLyXe/" + i);
            Data obj2 = resp2.ResultAs<Data>();

            DataRow row = dt.NewRow();

            row["maxe"] = obj2.MaXe;
            row["sdt"] = obj2.SDT;
            row["name"] = obj2.Name;
            row["bsx"] = obj2.BSX;
            row["timein"] = obj2.TimeIn;
            row["timeout"] = obj2.TimeOut;
            row["vitri"] = obj2.ViTri;

            dt.Rows.Add(row);
            Total();
        }
        catch
        {

        }
    }
}

Bước 2: Tạo hàm Total() để hiển thị tổng xe đã ra vào.

private void Total()
{
    int count = 0;
    if (dtgListCar.Rows.Count <= 0)
    {
        txtTotal.Text = "0";
    }
    else
    {
        count = Convert.ToInt32(dtgListCar.Rows.Count);
        txtTotal.Text = count.ToString();
    }
}

Bước 3: Tạo hàm Load() để tạo các Columns với các tiêu đề trên DataGridView, sau đó gọi hàm RetriveCar() để lấy danh sách.

void load()
{
    client = new FireSharp.FirebaseClient(config);

    dt.Columns.Add("maxe");
    dt.Columns.Add("name");
    dt.Columns.Add("sdt");
    dt.Columns.Add("bsx");
    dt.Columns.Add("timein");
    dt.Columns.Add("timeout");
    dt.Columns.Add("vitri");

    dtgListCar.DataSource = dt;

    dtgListCar.Columns[0].HeaderText = "Mã Xe";
    dtgListCar.Columns[1].HeaderText = "Họ và tên";
    dtgListCar.Columns[2].HeaderText = "Số điện thoại";
    dtgListCar.Columns[3].HeaderText = "Biển số xe";
    dtgListCar.Columns[4].HeaderText = "Thời gian vào";
    dtgListCar.Columns[5].HeaderText = "Thời gian ra";
    dtgListCar.Columns[6].HeaderText = "Vị trí đỗ";
    RetriveCar();
    Total();
}

Bước 4: Gọi hàm Load() ở sự kiện Form_Load để hiển thị danh sách ngay khi chương trình bắt đầu chạy.

private void Form1_Load(object sender, EventArgs e)
{
    load();
}

Kết quả: Mình đã thêm dữ liệu sẵn ở trên Firebase nên nó sẽ hiển thị như hình dưới đây, các bạn có thể tự thêm dữ liệu để kiểm tra nhé.

parking 01 png

Chức năng tìm kiếm

Ở chức năng tìm kiểm, mình sẽ xử lý ở sự kiện TextChanged của TextBox tìm kiếm. Cụ thể mình sẽ sử dụng RowFilter trong C# để tìm kiếm theo biển số xe. Trong lúc đó sẽ gọi hàm Total() để hiển thị tổng số xe theo số xe đang có trên DataGridView.

private void txtSearch_TextChanged(object sender, EventArgs e)
{
    string rowFilter = string.Format("{0} like '{1}'", "bsx", "*" + txtSearch.Text + "*");//"TenSP like *" + txtLocSanPham.text + "*"
    (dtgListCar.DataSource as DataTable).DefaultView.RowFilter = rowFilter;
    Total();
}

Kết quả:

parking 04 png

Chức năng Binding danh sách xe

Để thuận tiện cho việc xem và sửa thông tin chúng ta sẽ thực hiện Binding dữ liệu từ DataGridView vào các TextBox tương ứng. Cụ thể khi người dùng nhấn vào dữ liệu ở trên DataGridView, các dữ liệu trong hàng đó sẽ được hiển thị trên các TextBox tương ứng.

void BidingListCar()
{
    txtMaXe.DataBindings.Add(new Binding("Text", dtgListCar.DataSource, "maxe", true, DataSourceUpdateMode.Never));
    txtName.DataBindings.Add(new Binding("Text", dtgListCar.DataSource, "name", true, DataSourceUpdateMode.Never));
    txtNumber.DataBindings.Add(new Binding("Text", dtgListCar.DataSource, "sdt", true, DataSourceUpdateMode.Never));
    txtBSX.DataBindings.Add(new Binding("Text", dtgListCar.DataSource, "bsx", true, DataSourceUpdateMode.Never));
    txtViTri.DataBindings.Add(new Binding("Text", dtgListCar.DataSource, "vitri", true, DataSourceUpdateMode.Never));
    dtpickerTimeIn.DataBindings.Add(new Binding("Value", dtgListCar.DataSource, "timein", true, DataSourceUpdateMode.Never));
    dtpickerTimeOut.DataBindings.Add(new Binding("Value", dtgListCar.DataSource, "timeout", true, DataSourceUpdateMode.Never));
}

Kết quả:

parking 05 png

Chức năng làm mới

Với chức năng nay, khi người dùng nhấn chọn Button “Làm mới” các thông tin trong TextBox sẽ được xóa trắng. Vì để sử dụng lại nhiều lần, mình sẽ tạo một hàm reset() để làm việc này.

void reset()
{
    txtMaXe.Clear();
    txtBSX.Clear();
    txtName.Clear();
    txtNumber.Clear();
    txtViTri.Clear();
    dtpickerTimeIn.Value = DateTime.Today;
    dtpickerTimeOut.Value = DateTime.Today;
}

Chức năng thêm mới

Để thêm mới, việc đầu tiên chúng ta cần kiểm tra xem các thông tin đã được nhập đầy đủ hay chưa, nếu chưa thì cần có thông báo cho người dùng biết. Sau đó sẽ đẩy các dữ liệu đã nhập lên Firebase và gọi hàm reset() để xóa trắng dữ liệu trong các ô TextBox.

private async void AddCar()
{
    //kiểm tra thông tin của học sinh rồi mới thực hiện thêm mới
    if (txtName.Text == "")
    {
        MessageBox.Show("Vui lòng nhập họ và tên chủ xe", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtName.Focus();
    }
    else if (txtNumber.Text == "")
    {
        MessageBox.Show("Vui lòng nhập số điện thoại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtNumber.Focus();
    }
    else if (txtBSX.Text == "")
    {
        MessageBox.Show("Vui lòng nhập biển số xe", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtBSX.Focus();
    }
    else if (txtViTri.Text == "")
    {
        MessageBox.Show("Vui lòng nhập vị trí đỗ", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtViTri.Focus();
    }
    else
    {
        //lấy số lượng tổng học sinh
        FirebaseResponse resp = await client.GetTaskAsync("Count");
        Count get = resp.ResultAs<Count>();
        //khởi tạo một object thuộc Class Data
        var data = new Data
        {
            MaXe = (Convert.ToInt32(get.cnt) + 1).ToString(),
            Name = txtName.Text,
            BSX = txtBSX.Text,
            SDT = txtNumber.Text,
            TimeIn = dtpickerTimeIn.Text.ToString(),
            TimeOut = dtpickerTimeOut.Text.ToString(),
            ViTri = txtViTri.Text
        };

        //Đẩy dữ liệu lên Firebase
        SetResponse response = await client.SetTaskAsync("QuanLyXe/" + data.MaXe, data);
        Data result = response.ResultAs<Data>();

        MessageBox.Show("Đã thêm mới thành công !!");
        reset();

        var obj = new Count
        {
            cnt = data.MaXe
        };

        SetResponse response1 = await client.SetTaskAsync("Count", obj);
        RetriveCar();
    }
}

Tiếp đến ta sẽ gọi hàm AddCar() ở sự kiện Click của Button “Thêm”.

private void btnAdd_Click(object sender, EventArgs e)
{
    AddCar();
}

Kết quả:

parking 06 png

Chức năng sửa thông tin

Tương tự như chức năng thêm mới, trước khi sửa thông tin ta cần kiểm tra xem người dùng đã nhập đầy đủ thông tin hay chưa. Sau đó sử dụng phương thức UpdateTaskAsync() để cập nhật thông tin lên Firebase.

private async void UpdateCar()
{
    if (txtName.Text == "")
    {
        MessageBox.Show("Vui lòng nhập tên chủ xe", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtName.Focus();
    }
    else if (txtNumber.Text == "")
    {
        MessageBox.Show("Vui lòng nhập số điện thoại", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtNumber.Focus();
    }
    else if (txtBSX.Text == "")
    {
        MessageBox.Show("Vui lòng nhập biển số xe", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtBSX.Focus();
    }
    else if (txtViTri.Text == "")
    {
        MessageBox.Show("Vui lòng nhập vị trí đỗ xe", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        txtViTri.Focus();
    }
    else
    {
        var data = new Data
        {
            MaXe = txtMaXe.Text,
            Name = txtName.Text,
            SDT = txtNumber.Text,
            BSX = txtBSX.Text,
            ViTri = txtViTri.Text,
            TimeIn = dtpickerTimeIn.Text.ToString(),
            TimeOut = dtpickerTimeOut.Text.ToString()
        };

        FirebaseResponse response = await client.UpdateTaskAsync("QuanLyXe/" + txtMaXe.Text, data);
        Data result = response.ResultAs<Data>();
        MessageBox.Show("Sửa thành công xe có mã: " + result.MaXe, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
        reset();
        RetriveCar();
    }
}

Sau đó gọi hàm UpdateCar() ở sự kiện Click của Button “Sửa”.

private void btnUpdate_Click(object sender, EventArgs e)
{
    UpdateCar();
}

Kết quả:

parking 07 png

Chức năng xóa

Trước khi thực hiện xóa, ta cần hiển thị thông báo yêu cầu người dùng xác nhận. Nếu đồng ý ta sẽ sử dụng phương thức DeleteTaskAsync() để xóa dữ liệu trên Database.

private async void DeleteCar()
{
    DialogResult dg = MessageBox.Show("Bạn có chắc chắn xóa hết ?", "Thông báo", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
    if (dg == DialogResult.Yes)
    {
        int i = 0;
        FirebaseResponse resp1 = await client.GetTaskAsync("Count");
        Count obj1 = resp1.ResultAs<Count>();

        int cnt = Convert.ToInt32(obj1.cnt);

        while (true)
        {
            if (i == cnt)
                break;
            i++;
            try
            {
                FirebaseResponse response = await client.DeleteTaskAsync("Information/" + i);
                MessageBox.Show("Đã xóa hết thành công !!! ", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch
            {

            }
        }
        var obj = new Count
        {
            cnt = "0"
        };
        SetResponse response1 = await client.SetTaskAsync("Count", obj);
        reset();
        RetriveCar();
        txtTotal.Text = "0";
    }
}

Tiếp đến gọi hàm DeleteCar() ở sự kiện Click của Butoton “Xóa hết”.

private void btnDeleteAll_Click(object sender, EventArgs e)
{
    DeleteCar();
}

Kết quả:

parking 08 png

Chức năng thoát

Chức năng này khá đơn giản, hầu như ứng dụng nào cũng cần có nó cả. Ta sẽ hỏi người dùng có muốn thoát hay không, nếu có thì mới thoát, ngược lại không thì sẽ hủy bỏ lệnh.

private void btnExit_Click(object sender, EventArgs e)
{
    DialogResult dg = MessageBox.Show("Bạn có chắc muốn thoát?", "Thông báo", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
    if (dg == DialogResult.OK)
        Application.Exit();
}

Kết quả:

parking 09 png

Chức năng xuất danh sách ra file Excel

Chức năng xuất danh sách ra file Excel mình đã có hướng dẫn cụ thể ở một bài viết, các bạn có thể xem lại để hiểu rõ hơn nhé.

Ở đây mình sẽ tạo một hàm ToExcel() với hai tham số là DataGridView (danh sách xe) và SaveFileDialog (cửa sổ lưu file).

private void ToExcel(DataGridView dataGridView1, string fileName)
{
    Microsoft.Office.Interop.Excel.Application excel;
    Microsoft.Office.Interop.Excel.Workbook workbook;
    Microsoft.Office.Interop.Excel.Worksheet worksheet;

    try
    {
        excel = new Microsoft.Office.Interop.Excel.Application();
        excel.Visible = false;
        excel.DisplayAlerts = false;

        workbook = excel.Workbooks.Add(Type.Missing);

        worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Sheets["Sheet1"];
        worksheet.Name = "Quản lý học sinh";

        // export header
        for (int i = 0; i < dataGridView1.ColumnCount; i++)
        {
            worksheet.Cells[1, i + 1] = dataGridView1.Columns[i].HeaderText;
        }
        // export content
        for (int i = 0; i < dataGridView1.RowCount; i++)
        {
            for (int j = 0; j < dataGridView1.ColumnCount; j++)
            {
                worksheet.Cells[i + 2, j + 1] = dataGridView1.Rows[i].Cells[j].Value.ToString();
            }
        }
        // save workbook
        workbook.SaveAs(fileName);
        workbook.Close();
        excel.Quit();
        MessageBox.Show("Xuất dữ liệu ra Excel thành công!");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        workbook = null;
        worksheet = null;
    }
}

Sau đó gọi hàm ToExcel() ở sự kiện Click của Button “Xuất Excel”.

private void btnExportExcel_Click(object sender, EventArgs e)
{
    if (saveFileDialog1.ShowDialog() == DialogResult.OK)
    {
        ToExcel(dtgListCar, saveFileDialog1.FileName);
    }
}

Kết quả:

parking 10 png

Source code

Trên đây là ứng dụng quản lý xe ra vào C# Winforms và Firebase. Các bạn có thể áp dụng những kiến thức trên để tự tạo cho mình một ứng dụng riêng nhé. Mình sẽ để Source Code ở dưới đây để các bạn có thể tham khảo nhé, chúc các bạn thành công !!!

Ứng dụng quản lý xe ra vào C# Winforms và Firebase.

Bài viết liên quan

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *