none
自訂的class沒辦法存取屬性 RRS feed

  • 問題

  • 程式如下:

    請問這是一個我在datagridview中、自訂的Combobox元件。

    其中Columnwidths跟dropdownwidth是自訂的Property。

    但是當我在表單的設計頁中,設定了引用此class的column其columnwidths跟dropdownwidth、按下確定離開後再進去看,這2個自訂的屬性值就會不見

    請問有人知道為什麼嗎?謝謝

    Imports System
    Imports System.Windows.Forms
    Imports System.Windows.Media.LinearGradientBrush
    Imports System.Windows.Freezable
    Imports System.Drawing.Drawing2D
    Imports System.Drawing
    Public Class MCCColumn
      Inherits DataGridViewColumn
      Private _ColumnWidths As String
      Private _ColumnWidthsArray As String()
      Private _DropDownWidth As String
      Public Sub New()
        MyBase.New(New MCCCell())
        PCW = ColumnWidths
      End Sub
      Public Property ColumnWidths As String
        Get
          Return _ColumnWidths
        End Get
        Set(ByVal Value As String)
          _ColumnWidths = Value
          _ColumnWidthsArray = Value.Split(CType(";", Char))
          Dim w As Integer = 0
          For Each str As String In _ColumnWidthsArray
            w += CInt(str)
          Next str
          _DropDownWidth = w + 10
        End Set
      End Property
      Public Property DropDownWidth() As String
        Get
          Return _DropDownWidth
        End Get
        Set(ByVal Value As String)
          _DropDownWidth = Value
        End Set
      End Property
      Public Overrides Property CellTemplate() As DataGridViewCell
        Get
          Return MyBase.CellTemplate
        End Get
        Set(ByVal value As DataGridViewCell)
          If Not (value Is Nothing) AndAlso Not value.GetType().IsAssignableFrom(GetType(MCCCell)) Then
            Throw New InvalidCastException("Must be a CalendarCell")
          End If
          MyBase.CellTemplate = value
        End Set
      End Property
    End Class


    2011年7月6日 上午 06:16

解答

  • Hi,

    請覆寫處理Clone...

     

     Public Overrides Function Clone() As Object
    
      Dim newObj As MCCColumn = MyBase.Clone()
      With newObj
       .ColumnWidths = Me.ColumnWidths
      End With
      Return newObj
     End Function
    

    完整的程式如下...

     

     

    Public Class MCCColumn
     Inherits DataGridViewColumn
    
     Private _ColumnWidths As String
    
     Public Sub New()
      Me.CellTemplate = New DataGridViewTextBoxCell()
      'MyBase.New(New DataGridViewComboBoxCell)
      '_ColumnWidths = ColumnWidths
     End Sub
    
     Public Property ColumnWidths() As String
      Get
       Return Me._ColumnWidths
      End Get
    
      Set(ByVal value As String)
       Me._ColumnWidths = value
      End Set
     End Property
    
     Public Overrides Function Clone() As Object
    
      Dim newObj As MCCColumn = MyBase.Clone()
      With newObj
       .ColumnWidths = Me.ColumnWidths
      End With
      Return newObj
     End Function
    End Class
    


     


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/
    • 已標示為解答 Mindscold 2011年7月29日 上午 05:47
    2011年7月16日 上午 09:01

所有回覆

  • 屬性的內容值沒有儲存有一種情形是MCCColumn類別的物件被丟棄了, 您可以檢查一下看有沒有這種情形
    2011年7月6日 上午 11:18
  • 屬性的內容值沒有儲存有一種情形是MCCColumn類別的物件被丟棄了, 您可以檢查一下看有沒有這種情形
    請問被丟棄了是什麼意思?
    2011年7月7日 上午 02:00
  • 通常如果產生類別實體後會將某個(或幾個)變數指向該實體(Instance), 如果在程式執行的過程中, 這些變數被消滅 (例如宣告在function中的變數在function結束後就不見了), 消滅到完全沒有變數指向該實體參考時, CLR就有可能將其標註為可回收 (也就是被拋棄了 )
    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    2011年7月7日 上午 02:52
    版主
  • (過了這麼久才回覆 先說聲抱歉…)

    我後來將程式碼縮簡成這樣子:

    Imports System
    Imports System.Windows.Forms
    
    Public Class MCCColumn
      Inherits DataGridViewColumn
      Private _ColumnWidths As String
      
      Public Sub New()
    	MyBase.New(New DataGridViewComboBoxCell)
        _ColumnWidths = ColumnWidths
      End Sub
    
      Public Property ColumnWidths() As String
        Get
          Return Me._ColumnWidths
        End Get
        
        Set(ByVal value As String)
          Me._ColumnWidths = value
        End Set
        
      End Property
    End Class
    

    經過測試後,它還是沒辦法存設定值

    縮到這只剩這幾行,還是不能存,我真的不知道是在哪裡被丟棄了還是怎麼了?@@

    2011年7月15日 上午 07:25
  • 還要有應用程式如何使用MCCColumn的程式碼
    2011年7月15日 下午 01:48
  • Win Form 還是有生命週期的問題; 尤其是 template 容器, 被資料繫結後, 你必須考慮它值被重設的問題。
    ASP.NET 2Share - http://www.dotblogs.com.tw/johnny
    2011年7月16日 上午 01:10
  • 還要有應用程式如何使用MCCColumn的程式碼
    我是直接在form上拉一個datagridview後,加入資料行為MCCColumn
    2011年7月16日 上午 02:32
  • Win Form 還是有生命週期的問題; 尤其是 template 容器, 被資料繫結後, 你必須考慮它值被重設的問題。
    ASP.NET 2Share - http://www.dotblogs.com.tw/johnny
    我現在還沒有做到資料繫結的動作耶…所以沒有重設值的問題
    2011年7月16日 上午 02:32
  • 這一行拿掉試看看:

     _ColumnWidths = ColumnWidths

    2011年7月16日 上午 05:13
  • 這一行拿掉試看看:

     _ColumnWidths = ColumnWidths

    也是沒有用耶
    2011年7月16日 上午 08:23
  • Hi,

    請覆寫處理Clone...

     

     Public Overrides Function Clone() As Object
    
      Dim newObj As MCCColumn = MyBase.Clone()
      With newObj
       .ColumnWidths = Me.ColumnWidths
      End With
      Return newObj
     End Function
    

    完整的程式如下...

     

     

    Public Class MCCColumn
     Inherits DataGridViewColumn
    
     Private _ColumnWidths As String
    
     Public Sub New()
      Me.CellTemplate = New DataGridViewTextBoxCell()
      'MyBase.New(New DataGridViewComboBoxCell)
      '_ColumnWidths = ColumnWidths
     End Sub
    
     Public Property ColumnWidths() As String
      Get
       Return Me._ColumnWidths
      End Get
    
      Set(ByVal value As String)
       Me._ColumnWidths = value
      End Set
     End Property
    
     Public Overrides Function Clone() As Object
    
      Dim newObj As MCCColumn = MyBase.Clone()
      With newObj
       .ColumnWidths = Me.ColumnWidths
      End With
      Return newObj
     End Function
    End Class
    


     


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/
    • 已標示為解答 Mindscold 2011年7月29日 上午 05:47
    2011年7月16日 上午 09:01
  • Hi,

    請覆寫處理Clone...

     

     Public Overrides Function Clone() As Object
    
     Dim newObj As MCCColumn = MyBase.Clone()
     With newObj
      .ColumnWidths = Me.ColumnWidths
     End With
     Return newObj
     End Function
    

    完整的程式如下...

     

     

    Public Class MCCColumn
     Inherits DataGridViewColumn
    
     Private _ColumnWidths As String
    
     Public Sub New()
     Me.CellTemplate = New DataGridViewTextBoxCell()
     'MyBase.New(New DataGridViewComboBoxCell)
     '_ColumnWidths = ColumnWidths
     End Sub
    
     Public Property ColumnWidths() As String
     Get
      Return Me._ColumnWidths
     End Get
    
     Set(ByVal value As String)
      Me._ColumnWidths = value
     End Set
     End Property
    
     Public Overrides Function Clone() As Object
    
     Dim newObj As MCCColumn = MyBase.Clone()
     With newObj
      .ColumnWidths = Me.ColumnWidths
     End With
     Return newObj
     End Function
    End Class
    


     


    謙卑學習,持之以恆,才能不斷的Level Up http://www.dotblogs.com.tw/larrynung/

    你好,我試了你的程式後已經正常可以存取了,真是謝謝你

    我將這些程式碼放入我一開始要自訂的元件裡(一個DataGridView上的多欄Combobox)

    發現它沒有辦法傳遞這些我自訂的屬性數值

    Imports System
    Imports System.Windows.Forms
    Imports System.Windows.Media.LinearGradientBrush
    Imports System.Windows.Freezable
    Imports System.Drawing.Drawing2D
    Imports System.Drawing
    Public Class MCCColumn
      Inherits DataGridViewColumn
      Private _ColumnWidths As String
      Private _ColumnWidthsArray As String()
      Private _DropDownWidth As String
      Private _DS As String
       Public Sub New()
        Me.CellTemplate = New MCCCell()
        'MyBase.New(New DataGridViewComboBoxCell)
        '_ColumnWidths = ColumnWidths
      End Sub
      Public Property ColumnWidths() As String
        Get
          Return Me._ColumnWidths
    
        End Get
    
        Set(ByVal value As String)
          If IsNothing(value) Then
            Me._ColumnWidths = Me.Width.ToString
          Else
            Me._ColumnWidths = value
          End If
    
          Me._ColumnWidthsArray = Me._ColumnWidths.Split(CType(";", Char))
          Dim w As Integer = 0
          For Each str As String In Me._ColumnWidthsArray
            w += CInt(str)
          Next str
          Me._DropDownWidth = w + 10
        End Set
      End Property
      Public Property DropDownWidth() As String
        Get
          Return Me._DropDownWidth
        End Get
        Set(ByVal Value As String)
          Me._DropDownWidth = Value
        End Set
      End Property
      Public Property DS() As String
        Get
          Return Me._DS
        End Get
        Set(ByVal Value As String)
          Me._DS = Value
        End Set
      End Property
      Public Overrides Function Clone() As Object
        Dim newObj As MCCColumn = MyBase.Clone()
        With newObj
          ._ColumnWidths = Me._ColumnWidths
          ._DropDownWidth = Me._DropDownWidth
          ._DS = Me._DS
    
        End With
        Return newObj
      End Function
    End Class
    Public Class MCCCell
      Inherits DataGridViewComboBoxCell
      Private _ColumnWidths As String
      Private _ColumnWidthsArray As String()
      Private _DropDownWidth As String
      Private _DS As String
      Public Sub New()
        MyBase.new()
      End Sub
      Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
        ByVal initialFormattedValue As Object, _
        ByVal dataGridViewCellStyle As DataGridViewCellStyle)
    
        MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
        Dim ctl As MCCEditingControl = CType(DataGridView.EditingControl, MCCEditingControl)
        ctl._ColumnWidths = Me._ColumnWidths
        ctl._ColumnWidthsArray = Me._ColumnWidthsArray
        ctl._DropDownWidth = Me._DropDownWidth
        ctl._DS = Me._DS
    
      End Sub
      Public Overrides ReadOnly Property EditType() As Type
        Get
          Return GetType(MCCEditingControl)
        End Get
      End Property
    End Class
    Class MCCEditingControl
      Inherits MultiColumnCombo
      Implements IDataGridViewEditingControl
      Private dataGridViewControl As DataGridView
      Private valueIsChanged As Boolean = False
      Private rowIndexNum As Integer
      Public Sub New()
        MyBase.New()
      End Sub
      Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle) Implements System.Windows.Forms.IDataGridViewEditingControl.ApplyCellStyleToEditingControl
        Me.DrawMode = Windows.Forms.DrawMode.OwnerDrawFixed
        Dim Cnn As New Odbc.OdbcConnection("xxxxxxxxxxxxxxxxxxxxxxxxx")
        Cnn.Open()
        Dim Adp As New Odbc.OdbcDataAdapter(Me._DS, Cnn)
        Dim DS As New DataSet
        Adp.Fill(DS, "Parts")
    
        Dim BS As New BindingSource
        BS.DataSource = DS
        BS.DataMember = "Parts"
    
        Me.DataSource = BS
        Me.Font = dataGridViewCellStyle.Font
        Me.ColumnWidths = Me._ColumnWidths
        Me.DropDownWidth = Me._DropDownWidth
      End Sub
      Public Property EditingControlDataGridView As System.Windows.Forms.DataGridView Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlDataGridView
        Get
          Return dataGridViewControl
        End Get
        Set(ByVal value As System.Windows.Forms.DataGridView)
          dataGridViewControl = value
        End Set
      End Property
      Public Property EditingControlFormattedValue As Object Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlFormattedValue
        Get
          Return Me.Text
        End Get
        Set(ByVal value As Object)
        End Set
      End Property
      Public Property EditingControlRowIndex As Integer Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlRowIndex
        Get
          Return rowIndexNum
        End Get
        Set(ByVal value As Integer)
          rowIndexNum = value
        End Set
      End Property
      Public Property EditingControlValueChanged As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlValueChanged
        Get
          Return valueIsChanged
        End Get
        Set(ByVal value As Boolean)
          valueIsChanged = value
        End Set
      End Property
      Public Function EditingControlWantsInputKey(ByVal keyData As System.Windows.Forms.Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlWantsInputKey
        Select Case keyData And Keys.KeyCode
          Case Keys.Left, Keys.Up, Keys.Down, Keys.Right, _
            Keys.Home, Keys.End, Keys.PageDown, Keys.PageUp
    
            Return True
    
          Case Else
            Return False
        End Select
      End Function
      Public ReadOnly Property EditingPanelCursor As System.Windows.Forms.Cursor Implements System.Windows.Forms.IDataGridViewEditingControl.EditingPanelCursor
        Get
          Return MyBase.Cursor
        End Get
      End Property
      Public Function GetEditingControlFormattedValue(ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object Implements System.Windows.Forms.IDataGridViewEditingControl.GetEditingControlFormattedValue
        Return Me.Text
      End Function
      Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements System.Windows.Forms.IDataGridViewEditingControl.PrepareEditingControlForEdit
        ' No preparation needs to be done.
      End Sub
      Public ReadOnly Property RepositionEditingControlOnValueChange As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.RepositionEditingControlOnValueChange
        Get
          Return False
        End Get
      End Property
    End Class
    Public Class MultiColumnCombo
      Inherits System.Windows.Forms.ComboBox
      Public _ColumnWidths As String
      Public _ColumnWidthsArray As String()
      Public _DropDownWidth As String
      Public _DS As String
      Private _DoNotReact As Boolean = False
      Private _Textchanged As Boolean = False
    
      Sub New()
        MyBase.New()
        MyBase.DrawMode = DrawMode.OwnerDrawFixed
      End Sub
    
      Public Property ColumnWidths() As String
        Get
          Return _ColumnWidths
        End Get
        Set(ByVal Value As String)
          _ColumnWidths = Value
          _ColumnWidthsArray = Value.Split(CType(";", Char))
          Dim w As Integer = 0
          For Each str As String In _ColumnWidthsArray
            w += CInt(str)
          Next str
          MyBase.DropDownWidth = w + 10
        End Set
      End Property
      Public Overloads Property DropDownWidth As String
        Get
          Return _DropDownWidth
        End Get
        Set(ByVal Value As String)
          _DropDownWidth = Value
        End Set
      End Property
      Public Overloads Property DS As String
        Get
          Return _DS
        End Get
        Set(ByVal Value As String)
          _DS = Value
        End Set
      End Property
      Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
        Dim myBrush As Brush
    
        Dim LightColor As Color = Color.Blue
        Dim DarkColor As Color = Color.Black
        Dim GradBrush As Brush = New LinearGradientBrush(e.Bounds, LightColor, DarkColor, LinearGradientMode.Vertical)
    
        Select Case CInt((e.State And DrawItemState.Selected))
          Case DrawItemState.Selected
            myBrush = New SolidBrush(BackColor)
            e.Graphics.FillRectangle(GradBrush, e.Bounds)
          Case Else
            myBrush = New SolidBrush(ForeColor)
            e.Graphics.FillRectangle(New SolidBrush(BackColor), e.Bounds)
        End Select
    
        _ColumnWidthsArray = _ColumnWidths.Split(CType(";", Char))
        Dim str As String
        Dim row As DataRowView = (CType(MyBase.Items(e.Index), DataRowView))
        Dim newpos As Integer = e.Bounds.X
        Dim endpos As Integer = e.Bounds.X
    
        For indx As Integer = 0 To UBound(_ColumnWidthsArray)
          Dim ColLength As Integer = CType(_ColumnWidthsArray(indx), Integer)
          endpos += ColLength
    
          Dim Charaant As Integer = CInt(Math.Round(CDbl(ColLength) / 6.2))
          Dim rawitem As String = row.Item(indx).ToString()
    
          If ColLength <> 0 Then
            If Charaant > rawitem.Length Then
              str = rawitem
            Else
              str = rawitem.Substring(0, Charaant)
            End If
    
            Dim r As RectangleF = New RectangleF(newpos + 2, e.Bounds.Y, endpos - 1, e.Bounds.Height)
            e.Graphics.DrawString(str, e.Font, myBrush, r)
    
            If indx <= UBound(_ColumnWidthsArray) Then
              e.Graphics.DrawLine(New Pen(Color.Black), endpos, e.Bounds.Y, endpos, Me.ItemHeight * Me.MaxDropDownItems)
              e.Graphics.DrawLine(New Pen(Color.LightGray), endpos + 1, e.Bounds.Y, endpos + 1, Me.ItemHeight * Me.MaxDropDownItems)
            End If
          End If
    
          newpos = endpos
        Next
        myBrush.Dispose()
        GradBrush.Dispose()
      End Sub
    
      Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
    
        Dim foundIndex As Integer, textlngth As Integer
        If _DoNotReact = False Then
          If Me.AccessibilityObject.Value Is Nothing Then
            textlngth = 0
            Exit Sub
          Else
            textlngth = Me.AccessibilityObject.Value.Length
          End If
    
          If textlngth = 0 Then
            MyBase.OnTextChanged(e)
            _DoNotReact = False
            _Textchanged = False
            Exit Sub
          End If
    
          If textlngth <> 0 Then
    
            _DoNotReact = True
            foundIndex = FindString(Me.AccessibilityObject.Value)
            If foundIndex > -1 Then
              Me.SelectedIndex = foundIndex
              Me.Select(textlngth, Me.Text.Length - textlngth)
              Me.SelectionStart = textlngth
              _Textchanged = True
            Else
              _Textchanged = False
            End If
            _DoNotReact = False
          End If
          MyBase.OnTextChanged(e)
        End If
        _DoNotReact = False
    
    
    
      End Sub
    
      Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
        Select Case e.KeyCode
          Case Keys.Back, Keys.Enter, Keys.Delete
            _DoNotReact = True
          Case Keys.Down
            Me.DroppedDown = True
            Invalidate()
    
        End Select
    
        MyBase.OnKeyDown(e)
    
      End Sub
    End Class
    
    


    MCCColumn宣告一個新的MCCCell後,存在MCCColumn中的ColumnWidths、DropDownwith 與DS 屬性沒辦法傳給這個新的MCCell,請問是為什麼呢?

    謝謝!

    2011年7月18日 上午 07:21