- [SQLSERVER] Loại bỏ Restricted User trên database MSSQL
- [C#] Hướng dẫn tạo mã QRcode Style trên winform
- [C#] Hướng dẫn sử dụng temp mail service api trên winform
- [C#] Hướng dẫn tạo mã thanh toán VietQR Pay không sử dụng API trên winform
- [C#] Hướng Dẫn Tạo Windows Service Đơn Giản Bằng Topshelf
- [C#] Chia sẻ source code đọc dữ liệu từ Google Sheet trên winform
- [C#] Chia sẻ source code tạo mã QR MOMO đa năng Winform
- [C#] Chia sẻ source code phần mềm lên lịch tự động chạy ứng dụng Scheduler Task Winform
- [Phần mềm] Tải và cài đặt phần mềm Sublime Text 4180 full version
- [C#] Hướng dẫn download file từ Minio Server Winform
- [C#] Hướng dẫn đăng nhập zalo login sử dụng API v4 trên winform
- [SOFTWARE] Phần mềm gởi tin nhắn Zalo Marketing Pro giá rẻ mềm nhất thị trường
- [C#] Việt hóa Text Button trên MessageBox Dialog Winform
- [DEVEXPRESS] Chia sẻ code các tạo report in nhiều hóa đơn trên XtraReport C#
- [POWER AUTOMATE] Hướng dẫn gởi tin nhắn zalo từ file Excel - No code
- [C#] Chia sẻ code lock và unlock user trong domain Window
- [DEVEXPRESS] Vẽ Biểu Đồ Stock Chứng Khoán - Công Cụ Thiết Yếu Cho Nhà Đầu Tư trên Winform
- [C#] Hướng dẫn bảo mật ứng dụng 2FA (Multi-factor Authentication) trên Winform
- [C#] Hướng dẫn convert HTML code sang PDF File trên NetCore 7 Winform
- [C#] Hướng dẫn viết ứng dụng chat với Gemini AI Google Winform
[DEVEXPRESS] Hướng dẫn switch tab trong Fluent Design Form
Xin chào các bạn, bài viết hôm nay mình sẻ chia sẽ đến các bạn source code cách Switch Tab trên giao diện Fluent Design Form của Devexpress C#.
[DEVEXPRESS] SWITCH TAB FLUENT DESIGN FORM C#
Lý do mình viết bài Switch Tab này là do trong giao diện Fluent Design Form, Devexpress không có hỗ trợ chức năng MDI containers Form trên giao diện này.
Nên khi các bạn mở tab đều là đưa từng Usercontrol vào FluentDesignFormContainer.
Nên khi chúng ta muốn di chuyển qua lại giữa các tab đã mở lên sẽ vào lại từng menu trên HamburgerMenu để mở lại.
Dưới đây là giao diện mình thiết kế Switch Tab trên c#:
Khi mở một tab form, mình sẽ chụp màn hình lại của từng userControl khi add vào.
Và mình sẽ kết hợp FlyoutPanel và Gridcontrol ở chế độ LayoutView để hiển thị thumbnail tab như hình bên dưới.
Ở source code demo này mình có sử dụng TrackerProcess, để sử dụng Splash Screen Loading và Overlay winform.
Các bạn download code cuối bài để tham khảo và sử dụng.
Source code c# MainForm.cs:
using DevExpress.LookAndFeel;
using DevExpress.Mvvm;
using DevExpress.Skins;
using DevExpress.Utils.Drawing;
using DevExpress.Utils.Taskbar;
using DevExpress.Utils.Taskbar.Core;
using DevExpress.XtraBars;
using DevExpress.XtraBars.Navigation;
using DevExpress.XtraPrinting.Drawing;
using DevExpress.XtraSplashScreen;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Media.Imaging;
namespace FluentWinform
{
public partial class MainForm : DevExpress.XtraBars.FluentDesignSystem.FluentDesignForm
{
public List<TabOpened> dicFormOpened = new List<TabOpened>();
public string currentFormOpened = "";
public MainForm()
{
AppProvider.MainForm = this;
StartUpProcess.OnStart("Starting...");
InitializeComponent();
//Thread.Sleep(1000);
StartUpProcess.OnComplete();
//Thread.Sleep(1000);
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
}
private void accordionControlElement2_Click(object sender, EventArgs e)
{
OpenForm(uc_employees.Instance);
}
private void accordionControlElement3_Click(object sender, EventArgs e)
{
OpenForm(uc_customers.Instance);
}
private void Form1_Load(object sender, EventArgs e)
{
accordionControlElement2_Click(null, null);
accordionControl1.SelectedElement = elementEmployee;
}
public void OpenForm(UserControl userControl)
{
//formIsActive = userControl.Tag?.ToString();
if (!dicFormOpened.Exists(x => x.name == currentFormOpened))
{ foreach(Control item in div_container.Controls)
{
if (!string.IsNullOrEmpty(currentFormOpened) && item.Tag?.ToString() == currentFormOpened)
{
var image = GetImageFromControl(this);
var tabOpened = new TabOpened();
tabOpened.name = item.Tag.ToString();
tabOpened.UserControl = item;
tabOpened.image = image;
dicFormOpened.Add(tabOpened); ;
break;
}
}
}
if (!div_container.Controls.Contains(userControl))
{
OverlayLoading.handle = OverlayLoading.ShowProgressPanel(this);
Thread.Sleep(200);
div_container.Controls.Add(userControl);
userControl.Dock = DockStyle.Fill;
userControl.BringToFront();
OverlayLoading.CloseProgressPanel(OverlayLoading.handle);
}
else
{
userControl.BringToFront();
}
currentFormOpened = userControl.Tag?.ToString();
}
public class TabOpened{
public string name { set; get; }
public Control UserControl { set; get; }
public Image image { set; get; }
}
protected SkinElement GetSeparatorSkinElement(UserLookAndFeel lookAndFeel)
{
SkinElement elem = AccordionControlSkins.GetSkin(lookAndFeel.ActiveLookAndFeel)[AccordionControlSkins.SkinSeparator];
if (elem != null) return elem;
return CommonSkins.GetSkin(lookAndFeel.ActiveLookAndFeel)[CommonSkins.SkinLabelLine];
}
protected void DrawSeparator(GraphicsCache cache, AccordionElementBaseViewInfo elementInfo)
{
SkinElement skinElem = GetSeparatorSkinElement(elementInfo.ControlInfo.LookAndFeel);
Rectangle rect = new Rectangle(elementInfo.HeaderBounds.X, elementInfo.HeaderBounds.Bottom - skinElem.Size.MinSize.Height, elementInfo.HeaderBounds.Width, skinElem.Size.MinSize.Height);
SkinElementInfo skinElemInfo = new SkinElementInfo(skinElem, rect);
ObjectPainter.DrawObject(cache, SkinElementPainter.Default, skinElemInfo);
}
private void accordionControl1_CustomDrawElement(object sender, DevExpress.XtraBars.Navigation.CustomDrawElementEventArgs e)
{
int selectionWidth = 3;
SkinElement elem = HamburgerMenuSkins.GetSkin(UserLookAndFeel.Default)[HamburgerMenuSkins.SkinItem];
int _tag = Convert.ToInt32(e.ObjectInfo.Element.Tag);
if(_tag<0) return;
e.Handled = true;
e.DrawHeaderBackground();
e.DrawImage();
e.DrawText();
if (Equals(accordionControl1.SelectedElement, e.ObjectInfo.Element))
e.Cache.FillRectangle(Color.Orange, new Rectangle(e.ObjectInfo.HeaderBounds.Location, new Size(ScaleHelper.ScaleHorizontal(selectionWidth), e.ObjectInfo.HeaderBounds.Height)));
//e.Cache.FillRectangle(elem.GetForeColor(ObjectState.Pressed), new Rectangle(e.ObjectInfo.HeaderBounds.Location, new Size(ScaleHelper.ScaleHorizontal(selectionWidth), e.ObjectInfo.HeaderBounds.Height)));
float x = e.ObjectInfo.HeaderBounds.Width - e.ObjectInfo.HeaderBounds.X - e.ObjectInfo.TextBounds.X;
float y = e.ObjectInfo.TextBounds.Y;
Font fn = accordionControl1.Appearance.Item.Normal.Font;
if (_tag == 2)
{
int elementTag = e.ObjectInfo.Element.Tag is int ? (int)e.ObjectInfo.Element.Tag : -1;
ObjectState state = Equals(elementTag, _tag) ? ObjectState.Pressed : ObjectState.Hot;
var bounds = new Rectangle((int)x - 6, (int)y, 20, 20);
var myBrush = new SolidBrush(Color.DarkOrange);
using (GraphicsPath path = RoundedRect(bounds, 5))
{
e.Cache.FillPath(myBrush, path);
}
e.Cache.DrawString(dicFormOpened.Count.ToString(), fn, e.Cache.GetSolidBrush(elem.GetForeColor(state)), x, y);
}
if(_tag == 4)
{
DrawSeparator(e.Cache, e.ObjectInfo);
}
}
public Bitmap GetImageFromControl(Control control)
{
Size ctrlSize = control.Size;
Rectangle rect = new Rectangle(new Point(0, 0), ctrlSize);
using (Bitmap bitmap = new Bitmap(ctrlSize.Width, ctrlSize.Height))
{
Bitmap captureBitmap = new Bitmap(1024, 768, PixelFormat.Format32bppArgb);
Rectangle captureRectangle = Screen.AllScreens[0].Bounds;
Graphics captureGraphics = Graphics.FromImage(captureBitmap);
captureGraphics.CopyFromScreen(captureRectangle.Left, captureRectangle.Top, 0, 0, captureRectangle.Size);
return captureBitmap;
}
}
public static GraphicsPath RoundedRect(Rectangle bounds, int radius)
{
int diameter = radius * 2;
Size size = new Size(diameter, diameter);
Rectangle arc = new Rectangle(bounds.Location, size);
GraphicsPath path = new GraphicsPath();
if (radius == 0)
{
path.AddRectangle(bounds);
return path;
}
path.AddArc(arc, 180, 90);
arc.X = bounds.Right - diameter;
path.AddArc(arc, 270, 90);
arc.Y = bounds.Bottom - diameter;
path.AddArc(arc, 0, 90);
arc.X = bounds.Left;
path.AddArc(arc, 90, 90);
path.CloseFigure();
return path;
}
private void accordionControlElement2_Click_1(object sender, EventArgs e)
{
OpenForm(uc_log.Instance);
}
private void accordionControlElement20_Click(object sender, EventArgs e)
{
OpenForm(uc_systems.Instance);
}
private void elementSwitchTab_Click(object sender, EventArgs e)
{
if (dicFormOpened.Count > 0)
{
gridControl1.DataSource = null;
gridControl1.RefreshDataSource();
gridControl1.DataSource = dicFormOpened;
flyoutPanel1.Options.AnchorType = DevExpress.Utils.Win.PopupToolWindowAnchor.Center;
flyoutPanel1.Width = this.Width;
flyoutPanel1.Height = this.Height / 2;
flyoutPanel1.Hiding += FlyoutPanel1_Hiding;
OverlayFormShow.Instance.ShowFormOverlay(this);
flyoutPanel1.ShowPopup();
}
}
private void FlyoutPanel1_Hiding(object sender, DevExpress.Utils.FlyoutPanelEventArgs e)
{
OverlayFormShow.Instance.CloseProgressPanel();
}
private void flyoutPanel1_ButtonClick(object sender, DevExpress.Utils.FlyoutPanelButtonClickEventArgs e)
{
if (e.Button.Tag.ToString().Equals("close"))
{
flyoutPanel1.HidePopup();
}
}
private void layoutView1_CardClick(object sender, DevExpress.XtraGrid.Views.Layout.Events.CardClickEventArgs e)
{
var tabSelected = layoutView1.GetRow(e.RowHandle) as TabOpened;
OpenForm(tabSelected.UserControl as UserControl);
OverlayFormShow.Instance.CloseProgressPanel();
flyoutPanel1.HidePopup();
}
}
}
Thanks for watching!