SourceGrid zt


SourceGrid介紹和使用及實例舉例

先上圖,來一個簡單演示:
 

SourceGrid就是一個用於數據顯示的表格控件,這個控件比c#自帶的 DataGridView要強大很多,先不說他的原理,只說他的功能,可以實現各種自定義樣式、嵌入各種控件,如checkbox、Combobox、 Button、超級鏈接、其他自定義控件等等,另外他不依賴於數據源顯示,可以隨意控制其顯示的單元格;

一,使用方法:
    1.1 首先去下載一個SourceGrid控件庫,這個是開源控件,下載好后整理一套動態庫,放入你的項目里,主要有以下幾個:
    DevAge.Core.dll      //輔助核心
    DevAge.Windows.Forms.dll  //包裝了用於winform里的某些控件的定義
    log4net.dll  //日志庫
    SourceGrid.dll             //核心庫
    SourceGrid.Extensions.dll  //擴展庫
   
    1.2 新建一個winform工程,將這些類庫放入debug目錄下,然后在工具箱點右鍵,選擇項,點瀏覽,選擇SourceGrid.dll,加入到工具箱;
    然后像使用其他控件一樣,拖到窗體上;

技術互動


二,代碼的編寫;
    SourceGrid一般都是以純代碼實現;
   
    2.1首先我們建一個用於數據顯示的對象:
    public class Student
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public DateTime Birth { get; set; }
        public int Fee { get; set; }
    }

   2.2 增加數據:
    定義私有的實例變量:
    private List<Student> students = null;
    在窗體構造函數里初始化此變量:
           students = new List<Student>()
            {
                new Student(){ Name="張三",Gender="1",Birth=DateTime.Parse("1989-1-1"),Fee = 2500},
                new Student(){ Name="李四",Gender="0",Birth=DateTime.Parse("1989-12-10"),Fee = 2200},
                new Student(){ Name="王五",Gender="0",Birth=DateTime.Parse("1989-4-4"),Fee = 2800}
            };
  2.3 在SourceGrid里顯示,並統計所收學費總和;
    

2.3.1  定義方法GetData()
     首先初始化列:
            SourceGrid.Grid grid = grid1;
            grid.BorderStyle = BorderStyle.FixedSingle;
            grid.FixedRows = 1;
            grid.FixedColumns = 1;
           
            //初始化列
            int gridColumnsCount = 5;//設定列數
            int gridRowsCount = students.Count+2;//設定行數
            int gridWith = this.Width - 20;//設定寬度為當前窗體寬度
            int[] colsWidth = { 20, 160, 160, 100, 100 };//每列的寬度
            string[] colsText = { "", "姓名", "性別", "生日", "已收學費" };//每列的標題

            grid.Rows.Insert(0);
            grid.ColumnsCount = gridColumnsCount;
            grid.Width = gridWith;
         
            int otherColsWidth = 0;
            for (int i = 0; i < 5; i++)
            {
                SourceGrid.Cells.ColumnHeader head = new SourceGrid.Cells.ColumnHeader(colsText);
                head.AutomaticSortEnabled = false;//禁止排序
                if (i != grid.ColumnsCount - 1)
                {
                    grid.Columns.Width = colsWidth;
                    otherColsWidth += colsWidth;
                }
                else
                    grid.Columns.Width = grid1.Width - otherColsWidth - 2 * i;//讓最后一列鋪滿整個Grid
                grid[0, i] = head;              
            }

      其次,初始化行:
     //初始化所有單元格
            int rowsReadOnly = gridColumnsCount - 2;//設置某行為只讀
            for (int i = 0; i <gridRowsCount; i++)
            {
                int r = grid.RowsCount;
                grid.Rows.Insert(r);
                for (int j = 1; j < gridColumnsCount;j++ )
                {
                    grid[r, j] = new SourceGrid.Cells.Cell("", typeof(string));
                    if (i == rowsReadOnly)
                    {
                        grid[r, j].Editor = null;
                    }
                }
            }
     填充數據:
          //賦值
            int sum = 0;
            for (int i = 0; i < students.Count; i++)
            {
                int r = i + 1;
                grid[r, 1] .Value=students.Name;
                grid[r, 2] .Value= students.Gender;
                grid[r, 3] =new SourceGrid.Cells.Cell(students.Birth, typeof(DateTime));
                grid[r, 4] =new SourceGrid.Cells.Cell(students.Fee, typeof(int));
                sum += students.Fee;
            }
            //設置倒數第二行的高度,直接將最后一行擠到最底部;
            grid.Rows[grid1.Rows.Count - 2].Height = grid1.Height - grid1.Rows[0].Height * (grid1.RowsCount) + 10;
           
            //設置倒數第一行的內容
            grid[grid.Rows.Count - 1, 1] = new SourceGrid.Cells.Cell("總計:", typeof(string));
            grid[grid.Rows.Count - 1, 4] = new SourceGrid.Cells.Cell(sum.ToString() + "圓整", typeof(string));

摘錄一段網上的描述:
每個單元格由 4 個基本部分組成, 它們基於改進的“模式-外觀-控制器(Model-View-Controller)”模型
模式(Model): 模式是管理單元格取值的類, 它包含相關的取值或屬性, 並且與其他組件相聯系. 
外觀(View) : 外觀是繪制單元格, 並包含可視屬性的類. 
控制器(Controller) : 控制器是提供單元格行為的類.  編輯器(Editor) :
編輯器是定制單元格的編輯器的類.  這種划分為代碼提供了很大的彈性和可重用性, 可節約時間, 為每種定制類型提供可靠的基礎。  
為了較通用的要求一些類已經被准備和配置, 但是, 可能會需要以某些代碼行建立個性化單元格。

簡單的理解:
因此,如果想改變外觀,就選擇或者自定義VIEW,如果想要增加事件、行為,則要選擇或者自定義控制器,如果想進去用合適的控件編輯,則要選擇或自定義編輯器;

而單元格里面放的是個對象,這個對象可以是普通的單元格、也可以是按鈕、也可以是其他類型,等等;

具體的描述性文檔可以參照網上的詳細介紹:
http://wenku.baidu.com/view/9bde88eb0975f46527d3e156.html

下面給大家列舉一個實用的例子
先上圖:

技術互動
 

實現的功能:
1,自定義列,最后一列鋪滿整個grid;
2,第0列放一個按鈕,單擊此按鈕可以彈出窗口,選擇新窗口的某條記錄,記錄的結果顯示在此行相應的單元格里;
3,性別的選擇為下拉列表,且只能是枚舉里的值;
4,生日的選擇只能為日期,可以彈出日期選擇框選擇;
5,當前的行用滿了,則可以右鍵增加一行;
6,可以刪除選擇的行;
相應的代碼:
定義幾個實例變量:
        private int gridRowsCount = 10;//設定行數
        private int gridColumnsCount = 5;//設定列數
        private int[] colsWidth = { 20, 160, 160, 100, 100 };//每列的寬度
        private string[] colsText = { "", "姓名", "性別", "生日", "已收學費" };//每列的標題

定義一個初始化GRID方法,基本都有注解
private void GetGrid()
        {
            SourceGrid.Grid grid = grid1;
            #region 初始化grid
            grid.Redim(gridRowsCount, gridColumnsCount);
            //選擇模式為行
            grid.SelectionMode = SourceGrid.GridSelectionMode.Row;
            //設置固定列和固定行
            grid.FixedColumns = 1;
            grid.FixedRows = 1;
            //初始化列,最后一列鋪滿整個grid
            for (int i = 0,otherColsWidth = 0; i < gridColumnsCount; i++)
            {
                SourceGrid.Cells.ColumnHeader head = new SourceGrid.Cells.ColumnHeader(colsText[i]);
                head.AutomaticSortEnabled = false;//取消自動排序
                if (i != grid.ColumnsCount - 1)//不是最后一列
                {
                    grid.Columns[i].Width = colsWidth[i];
                    otherColsWidth += colsWidth[i];
                }
                else //設置最后一列鋪滿整個grid
                    grid.Columns[i].Width = grid1.Width - otherColsWidth - 2 * i;
                grid[0, i] = head;
            }
            //初始化行
            for (int i = 1; i < gridRowsCount; i++)
            {
                IniOneRow(i);
            }
            #endregion
        }
其中有個初始化某行,代碼見下:

/// <summary>
        /// 初始化一行
        /// </summary>
        /// <param name="rowIndex"></param>
        private void IniOneRow(int rowIndex)
        {
            SourceGrid.Grid grid = grid1;
            //單擊控制器
            SourceGrid.Cells.Controllers.Button buttonClickEvent = new SourceGrid.Cells.Controllers.Button();
            buttonClickEvent.Executed += new EventHandler(CellButton_Click);
            //下拉框 暫時沒用到
            //SourceGrid.Cells.Editors.ComboBox cbEditor = new SourceGrid.Cells.Editors.ComboBox(typeof(EnumGender));
            //cbEditor.StandardValues = new EnumGender[] { EnumGender.男, EnumGender.女 };
            //cbEditor.EditableMode = SourceGrid.EditableMode.Focus | SourceGrid.EditableMode.SingleClick | SourceGrid.EditableMode.AnyKey;
            //日期編輯器
            SourceGrid.Cells.Editors.TextBoxUITypeEditor editorDateTime = new SourceGrid.Cells.Editors.TextBoxUITypeEditor(typeof(DateTime));
            PopupMenu menuController = new PopupMenu(this);
            for (int j = 0; j < gridColumnsCount; j++)
            {
                if (j == 0)
                {
                    //單元格設置為按鈕
                    grid[rowIndex, j] = new SourceGrid.Cells.Button("…");
                    //存放某些必須的信息,如關鍵字
                    grid[rowIndex, j].Tag = rowIndex;
                    //為按鈕增加事件
                    grid[rowIndex, j].AddController(buttonClickEvent);
                }
                else if (j == 2)
                {
                    //設置為枚舉類型,激活之后將會顯示為下拉框
                    grid[rowIndex, j] = new SourceGrid.Cells.Cell(null, typeof(EnumGender));
                    //grid[i, j].Editor = cbEditor;
                    //grid[i, j].View = SourceGrid.Cells.Views.ComboBox.Default;
                }
                else if (j == 3)//日期格式,控制其 顯示和輸入
                {
                    grid[rowIndex, j] = new SourceGrid.Cells.Cell("", typeof(DateTime));
                    grid1[rowIndex, j].Editor = editorDateTime;
                }
                else
                    grid[rowIndex, j] = new SourceGrid.Cells.Cell("", typeof(string));
                //設置每行的激活編輯方式
                if (grid[rowIndex, j].Editor!=null)
                    grid[rowIndex, j].Editor.EditableMode = SourceGrid.EditableMode.Focus | SourceGrid.EditableMode.SingleClick;
                    //grid[rowIndex, j].Editor.EditableMode = SourceGrid.EditableMode.Focus | SourceGrid.EditableMode.SingleClick | SourceGrid.EditableMode.AnyKey;
                //為每個行增加右鍵菜單
                grid[rowIndex, j].AddController(menuController);

            }
        }

這里稍微有點復雜:
1,了解按鈕控件如何放單元格里;
2,按鈕的事件如何關聯
2,了解枚舉類型如何處理;
3,如何增加菜單。對於菜單部分,還有部分代碼如下:

本帖最后由 繁華都市 於 2013-1-11 10:57 編輯

 


/// <summary>
        /// 按鈕單擊事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CellButton_Click(object sender, EventArgs e)
        {
            SourceGrid.CellContext context = (SourceGrid.CellContext)sender;
            SourceGrid.Cells.Button btnCell = (SourceGrid.Cells.Button)context.Cell;
            string id = btnCell.Tag.ToString();
            MessageBox.Show(id);
            Student stu = new Student() { Name = "張三", Gender = "1", Birth = DateTime.Parse("1991-1-1"), Fee = 2500 };
            EnumGender sGender = stu.Gender == "1" ? EnumGender.男 : EnumGender.女;
            int currenRow = btnCell.Row.Index;
            grid1[currenRow, 1].Value = stu.Name;
            grid1[currenRow, 2].Value = sGender;
            grid1[currenRow, 3].Value = stu.Birth;
            grid1[currenRow, 4].Value = stu.Fee;
        }

下面是菜單的兩個操作定義:
  /// <summary>
        /// 新增一行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Menu1_Click(object sender, EventArgs e)
        {
            int i = grid1.RowsCount;
            grid1.Rows.Insert(i);
            IniOneRow(i);
        }
        /// <summary>
        /// 刪除一行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Menu2_Click(object sender, EventArgs e)
        {
            //TODO Your code here
            int[] rowsIndex = grid1.Selection.GetSelectionRegion().GetRowsIndex();
            SourceGrid.RowInfo[] rows = new SourceGrid.RowInfo[rowsIndex.Length];
            for (int i = 0; i < rows.Length; i++)
                rows = grid1.Rows[rowsIndex【i】];

   foreach (SourceGrid.RowInfo r in rows)
                grid1.Rows.Remove(r.Index);
            if (grid1.RowsCount > 1)
                grid1.Selection.FocusRow(1);
        }

菜單控制器的定義如下:
  public class PopupMenu : SourceGrid.Cells.Controllers.ControllerBase
    {
        ContextMenu menu = new ContextMenu();
        private FormGridEdit mFrm;
        public PopupMenu(FormGridEdit frm)
        {
            mFrm = frm;
            menu.MenuItems.Add("新增一行", new EventHandler(mFrm.Menu1_Click));
            menu.MenuItems.Add("刪除選中的行", new EventHandler(mFrm.Menu2_Click));
        }
        public override void OnMouseUp(SourceGrid.CellContext sender, MouseEventArgs e)
        {
            base.OnMouseUp(sender, e);
            if (e.Button == MouseButtons.Right)
                menu.Show(sender.Grid, new Point(e.X, e.Y));
        }
      
    }

性別的枚舉:
    /// <summary>
    /// 枚舉,為下拉框准備
    /// </summary>
    public enum EnumGender
    {
        男,
        女,
        無
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM