none
如何擴充DataGridTextBoxColumn以便使多個關聯資料表的資料同時顯示在DataGrid資料行中 RRS feed

  • 問題

  • 請問各位高手

    小弟在書店中有找到VB的作法,但在自行轉成C# 語法,出現很多問題,

    是不可提供一點建議或是c#範例, 謝謝!

    2006年3月9日 下午 11:45

解答

  • 你把你前段的程式碼中的:

    protected  override object GetColumnValueAtRow(CurrencyManager cm,int rownum)

    {

        try

        {

            DataRow dr = ((DataView)cm.List).Table.Rows[rownum];//從CurrencyManager取得作用DataRow

            DataRow drparent = dr.GetParentRow(m_relationname); //DataRelation名稱來取得父資料列

            return drparent[m_parentfiled].ToString();//從父資料列傳回欄位值                     

        }

        catch

        {

            return "";

        }

    }

     

    改成:

     

    protected  override object GetColumnValueAtRow(CurrencyManager cm,int rownum)

    {

        try

        {

            DataRow dr = ((DataView)cm.List).Table.Rows[rownum];//從CurrencyManager取得作用DataRow

            DataRow drparent = dr.GetParentRow(m_relationname); //DataRelation名稱來取得父資料列

            return drparent[m_parentfiled].ToString();//從父資料列傳回欄位值                     

        }

        catch (Exception ex)

        {

            return "";

        }

    }

    2006年3月29日 上午 03:18
    版主

所有回覆

  • 你可以把那個程式碼貼上來,可以幫你看看 .
    2006年3月10日 上午 02:49
    版主
  • 感謝!小朱版主

    程式碼如下:

    //加入關聯 銷售主檔sale1_dt -> 會員檔fcustomer_dt

    DataColumn pa_s1c = appds.Tables["sale1_dt"].Columns["customer_no"];

    DataColumn ch_s1c = appds.Tables["fcustomer_dt"].Columns["no"];

    DataRelation re_s1c = new DataRelation("s1c",pa_s1c,ch_s1c,false);

    appds.Relations.Add(re_s1c);

    //新增"tname"傀儡欄位來對應jointextboxcolumn物件去對應

    appds.Tables["sale1_dt"].Columns.Add("tname",typeof(String));

    //設定(DataGrid銷售主檔) sale1_dataGrid資料

    sale1_dataGrid.SetDataBinding(appds,"sale1_dt");

    DataGridTableStyle sale1_style = new DataGridTableStyle();

    //設定DataGridStyle(銷售主檔)

    sale1_style.MappingName = "sale1_dt";

    DataGridColumnStyle col1_s1 = new DataGridTextBoxColumn();        //銷售編號

    col1_s1.MappingName = "sno1";

    col1_s1.HeaderText = "銷售編號";

    sale1_style.GridColumnStyles.Add(col1_s1);

    col1_s1 = new JoinTextBoxColumn("s1c",appds.Tables["fcustomer"].Columns["tname"]); //tname會員姓名 "來自會員資料檔"

    col1_s1.MappingName = "tname";                                                                  col1_s1.HeaderText = "會員姓名";

    sale1_style.GridColumnStyles.Add(col1_s1);               

    sale1_dataGrid.TableStyles.Add(sale1_style);

    private class JoinTextBoxColumn: DataGridTextBoxColumn

               {

                    private string m_relationname;

                    private DataColumn m_parentfiled;

                    public JoinTextBoxColumn(string relationname,DataColumn parentfiled)

                    {

                         m_relationname = relationname;

                         m_parentfiled = parentfiled;

                         base.ReadOnly = true ;

    }

                    protected  override object GetColumnValueAtRow(CurrencyManager cm,int rownum)

                    {

                         try

                         {

                              DataRow dr = ((DataView)cm.List).Table.Rows[rownum];//從CurrencyManager取得作用DataRow

                              DataRow drparent = dr.GetParentRow(m_relationname);     //DataRelation名稱來取得父資料列                    

                              return drparent[m_parentfiled].ToString();//從父資料列傳回欄位值                     

                         }

                         catch

                         {

                              return "";

                         }

                    }

                   

                    protected override bool Commit(CurrencyManager cm,int rownum)

                    {

                         return false ;    //由於是唯讀的,因此直接傳回false

                    }

         }

     

    2006年3月12日 下午 03:41
  • 這樣看好像看不出問題 ...
    你遇到的錯誤可以說一下嗎?
    2006年3月13日 上午 03:00
    版主
  • 問題: "會員姓名" 欄位 值變成空白.

    小弟認為很可能是 protected  override object GetColumnValueAtRow(CurrencyManager cm,int rownum) 這段有問題 ,但又無法確定, 謝謝!

    ps.原本想貼上畫面圖檔,但無法貼上.

    另外有段相關程式碼VB,不會翻成C#

    Public Shadows ReadOnly Property [ReadOnly]() As Boolean
                '
                ' 遮蔽基底屬性使其不能被設定。
                ' 傳回 True,如此一來 DataGrid 控制項將不允許編輯。
                '
                Get
                    Return True
                End Get
    End Property

    2006年3月13日 下午 08:47
  • 執到這行程式碼 return drparent[m_parentfiled].ToString();//從父資料列傳回欄位 出現錯誤

    錯誤訊息 :Message="並未將物件參考設定為物件的執行個體"

    2006年3月15日 下午 03:06
  • 你要不要把 VB 的程式貼上來看看?
    這樣也許比看 C# 更快 ...
    2006年3月28日 上午 09:41
    版主
  • 感謝小朱.版主熱心幫助.VB原程式碼如下:

    ' 匯入命名空間。
    Imports System.Data.SqlClient
    Public Class DemoForm47
        Inherits System.Windows.Forms.Form

        Private ds As DataSet
        Private cManager As BindingManagerBase

    #Region " Windows Form 設計工具產生的程式碼 "

        Public Sub New()
            MyBase.New()

            '此為 Windows Form 設計工具所需的呼叫。
            InitializeComponent()

            '在 InitializeComponent() 呼叫之後加入所有的初始設定

        End Sub

        'Form 覆寫 Dispose 以清除元件清單。
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                If Not (components Is Nothing) Then
                    components.Dispose()
                End If
            End If
            MyBase.Dispose(disposing)
        End Sub

        '為 Windows Form 設計工具的必要項
        Private components As System.ComponentModel.IContainer

        '注意: 以下為 Windows Form 設計工具所需的程序
        '您可以使用 Windows Form 設計工具進行修改。
        '請勿使用程式碼編輯器來修改這些程序。
        Friend WithEvents DataGrid1 As System.Windows.Forms.DataGrid
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            Me.DataGrid1 = New System.Windows.Forms.DataGrid
            CType(Me.DataGrid1, System.ComponentModel.ISupportInitialize).BeginInit()
            Me.SuspendLayout()
            '
            'DataGrid1
            '
            Me.DataGrid1.AccessibleDescription = ""
            Me.DataGrid1.AccessibleName = ""
            Me.DataGrid1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                        Or System.Windows.Forms.AnchorStyles.Left) _
                        Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
            Me.DataGrid1.BackgroundColor = System.Drawing.SystemColors.InactiveCaptionText
            Me.DataGrid1.CaptionText = "客戶、訂單以及員工資料"
            Me.DataGrid1.DataMember = ""
            Me.DataGrid1.Font = New System.Drawing.Font("新細明體", 12.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(136, Byte))
            Me.DataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText
            Me.DataGrid1.Location = New System.Drawing.Point(5, 9)
            Me.DataGrid1.Name = "DataGrid1"
            Me.DataGrid1.Size = New System.Drawing.Size(819, 433)
            Me.DataGrid1.TabIndex = 13
            '
            'DemoForm47
            '
            Me.AutoScaleBaseSize = New System.Drawing.Size(6, 18)
            Me.ClientSize = New System.Drawing.Size(829, 451)
            Me.Controls.Add(Me.DataGrid1)
            Me.Name = "DemoForm47"
            Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
            Me.Text = "示範如何同時將關聯資料表的資料列同時顯示在 DataGrid 控制項中"
            CType(Me.DataGrid1, System.ComponentModel.ISupportInitialize).EndInit()
            Me.ResumeLayout(False)

        End Sub

    #End Region

        Private Sub DemoForm47_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            '
            ' 讀取資料並建立資料表間的關聯性連結。
            '
            Dim cn As New SqlConnection("Server=(local)\NetSDK;DataBase=北風貿易;Integrated Security=SSPI")
            Dim daCust As New SqlDataAdapter("SELECT * FROM 客戶", cn)
            Dim daEmp As New SqlDataAdapter("SELECT * FROM 員工", cn)
            Dim daOrd As New SqlDataAdapter("SELECT * FROM 訂貨主檔 Order By 客戶編號", cn)
            ds = New DataSet
            daCust.Fill(ds, "客戶")
            daEmp.Fill(ds, "員工")
            daOrd.Fill(ds, "訂貨主檔")
            ds.Relations.Add("CustOrd", ds.Tables!客戶.Columns!客戶編號, ds.Tables!訂貨主檔.Columns!客戶編號)
            ds.Relations.Add("EmpOrd", ds.Tables!員工.Columns!員工編號, ds.Tables!訂貨主檔.Columns!員工編號)

            '
            ' 新增一些傀儡欄位來讓 JoinTextBoxColumn 物件去對應。
            ' 雖然我們稍後會將 JoinTextBoxColumn 物件的 MappingName
            ' 屬性設定成這些傀儡欄位,然而實際上於資料行中所顯示者
            ' 是於 JoinTextBoxColumn 物件之引數中所指定之關聯資料表
            ' 的欄位。其實只有當您所要對應的欄位數目超過來源資料表
            ' 中的欄位數目時才需要這樣做,在此我們是刻意這樣處理以
            ' 便讓您瞭解可以這樣做。您可以將 JoinTextBoxColumn
            ' 類別對應至任何欄位,畢竟實際於資料行中所顯示的資料是
            ' JoinTextBoxColumn 物件之引數中所指定之關聯資料表的欄位。
            '
            With ds.Tables!訂貨主檔
                .Columns.Add("姓名", GetType(String))
                .Columns.Add("名", GetType(String))
                .Columns.Add("公司名稱", GetType(String))
                .Columns.Add("連絡人", GetType(String))
            End With

            '
            ' 替來源資料表的各個欄位分別建立一個標準
            ' 的 DataGridTextBoxColumn 物件,以便使
            ' 它們能夠在 DataGrid 控制項中被編輯。
            ' 替各個關聯資料表的欄位分別建立一個自訂
            ' 的 JoinTextBoxColumn 物件,這些關聯資
            ' 料表欄位在 DataGrid 控制項中將是唯讀的。
            '
            Dim ts As New DataGridTableStyle
            ts.MappingName = "訂貨主檔"

            Dim cs As DataGridColumnStyle

            cs = New DataGridTextBoxColumn
            cs.Width = 90
            cs.MappingName = "訂單號碼"
            cs.HeaderText = "訂單號碼"
            ts.GridColumnStyles.Add(cs)

            cs = New DataGridTextBoxColumn
            cs.Width = 90
            cs.MappingName = "員工編號"
            cs.HeaderText = "員工編號"
            ts.GridColumnStyles.Add(cs)

            cs = New JoinTextBoxColumn("EmpOrd", ds.Tables!員工.Columns!姓名)
            cs.Width = 95
            cs.MappingName = "姓名"
            cs.HeaderText = "姓名"
            ts.GridColumnStyles.Add(cs)

            cs = New JoinTextBoxColumn("EmpOrd", ds.Tables!員工.Columns!名)
            cs.Width = 75
            cs.MappingName = "名"
            cs.HeaderText = "英文名"
            ts.GridColumnStyles.Add(cs)

            cs = New DataGridTextBoxColumn
            cs.Width = 90
            cs.MappingName = "客戶編號"
            cs.HeaderText = "客戶編號"
            ts.GridColumnStyles.Add(cs)

            cs = New JoinTextBoxColumn("CustOrd", ds.Tables!客戶.Columns!公司名稱)
            cs.Width = 150
            cs.MappingName = "公司名稱"
            cs.HeaderText = "公司名稱"
            ts.GridColumnStyles.Add(cs)

            cs = New JoinTextBoxColumn("CustOrd", ds.Tables!客戶.Columns!連絡人)
            cs.Width = 70
            cs.MappingName = "連絡人"
            cs.HeaderText = "連絡人"
            ts.GridColumnStyles.Add(cs)

            cs = New DataGridTextBoxColumn
            cs.Width = 100
            cs.MappingName = "訂單日期"
            cs.HeaderText = "訂單日期"
            ts.GridColumnStyles.Add(cs)

            DataGrid1.TableStyles.Add(ts)

            DataGrid1.DataSource = ds
            DataGrid1.DataMember = "訂貨主檔"

            cManager = BindingContext(DataGrid1.DataSource, DataGrid1.DataMember)
            DataGrid1.CaptionText &= "──共 " & cManager.Count.ToString & " 筆資料。"
        End Sub

        Class JoinTextBoxColumn
            Inherits DataGridTextBoxColumn

            '
            ' 持有資訊以便用於取得參考資料表中的欄位。
            '
            Private m_RelationName As String
            Private m_ParentField As DataColumn

            Public Sub New(ByVal RelationName As String, ByVal ParentField As DataColumn)
                m_RelationName = RelationName
                m_ParentField = ParentField
                ' 此資料行的基底樣式是唯讀的。
                MyBase.ReadOnly = True
            End Sub

            Protected Overrides Function GetColumnValueAtRow(ByVal cm As CurrencyManager, ByVal RowNum As Integer) As Object
                Try
                    ' 從 CurrencyManager 取得作用的 DataRow 。
                    Dim dr As DataRow = CType(cm.List, DataView).Item(RowNum).Row
                    ' 使用 GetParentRow 方法與 DataRelation 名稱來取得父資料列。
                    Dim drParent As DataRow = dr.GetParentRow(m_RelationName)
                    ' 從父資料列傳回欄位值。
                    Return drParent(m_ParentField).ToString()
                Catch
                    ' 處理當新增資料列時所引發的 NullReferenceException 例外狀況。
                    Return ""
                End Try
            End Function

            Protected Overrides Function Commit(ByVal cm As CurrencyManager, ByVal RowNum As Integer) As Boolean
                ' 由於是唯讀的,因此直接傳回 False。
                Return False
            End Function

            Public Shadows ReadOnly Property [ReadOnly]() As Boolean
                '
                ' 遮蔽基底屬性使其不能被設定。
                ' 傳回 True,如此一來 DataGrid 控制項將不允許編輯。
                '
                Get
                    Return True
                End Get
            End Property
        End Class
    End Class

    2006年3月28日 下午 10:57
  • 你把你前段的程式碼中的:

    protected  override object GetColumnValueAtRow(CurrencyManager cm,int rownum)

    {

        try

        {

            DataRow dr = ((DataView)cm.List).Table.Rows[rownum];//從CurrencyManager取得作用DataRow

            DataRow drparent = dr.GetParentRow(m_relationname); //DataRelation名稱來取得父資料列

            return drparent[m_parentfiled].ToString();//從父資料列傳回欄位值                     

        }

        catch

        {

            return "";

        }

    }

     

    改成:

     

    protected  override object GetColumnValueAtRow(CurrencyManager cm,int rownum)

    {

        try

        {

            DataRow dr = ((DataView)cm.List).Table.Rows[rownum];//從CurrencyManager取得作用DataRow

            DataRow drparent = dr.GetParentRow(m_relationname); //DataRelation名稱來取得父資料列

            return drparent[m_parentfiled].ToString();//從父資料列傳回欄位值                     

        }

        catch (Exception ex)

        {

            return "";

        }

    }

    2006年3月29日 上午 03:18
    版主