انتساب یک فرم به یک Property در VB.net

ms_vb

Member
سلام
چطور میتونم یک Property رو به یک فرم نسبت بدم
یه چیزی تو مایه های DefultCellStyle توی Data grid view که یه فرم جدید باز میکنه (CellStyleBuilder) و تنظیمات مربوطه رو توی اون فرم میپرسه
ممنون میشم راهنمایی کنید:rose:
 

the_king

مدیرکل انجمن
سلام
چطور میتونم یک Property رو به یک فرم نسبت بدم
یه چیزی تو مایه های DefultCellStyle توی Data grid view که یه فرم جدید باز میکنه (CellStyleBuilder) و تنظیمات مربوطه رو توی اون فرم میپرسه
ممنون میشم راهنمایی کنید:rose:

ساده است :

1) اون فرم دلخواه تون رو طراحی کنید. در طراحی تون هم این نکته رو در نظر بگیرید که یک Property Editor باید بتونه مقدار یا مقادیری
رو با Property Grid تبادل کنه، مقداری رو از خارج از کلاس فرم اش بخونه و بعد از تغییر برگردونه. پس اون فرم حداقل به یک متغیر یا Property یا
کنترل Public / Protected احتیاج داره.

2) سپس باید یک UITypeEditor اختصاصی بسازید که به اون Propery خاص نسبت بدید، در این UITypeEditor اون فرم مورد نظرتان با کد نویسی
نمایش داده می شود.

3) کد اون Property رو تغییر بدهید که از اون UITypeEditor اختصاصی استفاده کنه.

فرضا یک کمپوننت یا هر کلاس دیگری داریم به نام MyComponent که یک Property به نام Power داره که می تونه False یا True باشه :
کد:
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
Imports System

Public Class MyComponent

[B][COLOR="#0000FF"]    Private _power As Boolean

    Public Property Power() As Boolean
        Get
            Return _power
        End Get
        Set(ByVal value As Boolean)
            _power = value
        End Set
    End Property
[/COLOR][/B]
End Class
حالا می خواهیم این مشخصه Power در یک فرم اختصاصی ویرایش بشه.

1) در مرحله اول یک فرم می سازیم با نام PowerForm که دو تا RadioButton برای دو وضعیت Off و On داره و مشخصه Modifiers
هر دو شون Public ئه. دو تا دکمه OK و Cancel هم روی فرم داریم که مشخصه DialogResult اون تا دکمه روی OK و Cancel تنظیم شده.

2) یک کلاس UITypeEditor اختصاصی می سازیم به نام PowerUITypeEditor که از فرم PowerForm استفاده می کنه :
کد:
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
Imports System

Public Class PowerUITypeEditor
    Inherits UITypeEditor

    Public Overrides Function GetEditStyle(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.Drawing.Design.UITypeEditorEditStyle
[B][COLOR="#0000FF"]        Return UITypeEditorEditStyle.Modal[/COLOR][/B]
    End Function

    Public Overrides Function EditValue(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal provider As System.IServiceProvider, ByVal value As Object) As Object
        Dim service As IWindowsFormsEditorService = provider.GetService(GetType(IWindowsFormsEditorService))
        If (service Is Nothing) Or (value Is Nothing) Then
            Return value
        End If
[B][COLOR="#0000FF"]        Dim power As Boolean = value
        Using f As New PowerForm
            f.RadioButtonOff.Checked = Not power
            f.RadioButtonOn.Checked = power
            If service.ShowDialog(f) = DialogResult.OK Then
                power = f.RadioButtonOn.Checked
            End If
        End Using
        Return power
[/COLOR][/B]
    End Function

End Class

3) به اون مشخصه Power ای که در MyComponent داشتیم دو تا سطر اضافه می کنیم تا از PowerUITypeEditor استفاده کنه :
کد:
[CODE]
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
Imports System

Public Class MyComponent

    Private _power As Boolean

[B][COLOR="#0000FF"]    <Editor(GetType(PowerUITypeEditor), GetType(UITypeEditor))> _
    <TypeConverter(GetType(ExpandableObjectConverter))> _
[/COLOR][/B]    Public Property Power() As Boolean
        Get
            Return _power
        End Get
        Set(ByVal value As Boolean)
            _power = value
        End Set
    End Property

End Class
[/CODE]

یک پروژه با همین مثال پیوست شده است.
مشاهده پیوست CustomModalUITypeEditor.zip
 

ms_vb

Member
خیلی ممنونم از جواب کاملتون استاد گرامی
حالا اگه بخوام DataType ی که میسازم وقتی که به عنوان Property در نظر گرفته میشه این فرم رو نشون بده چه باید بکنم؟
یه جورایی مثل System.Windows.Forms.DockStyle که هر پروپرتی که از اون نوع تعریف بشه فرم مربوط به این DataType رو نشون میده
بازهم ممنونم از راهنمایی های کاملتون
 
آخرین ویرایش:

the_king

مدیرکل انجمن
خیلی ممنونم از جواب کاملتون استاد گرامی
حالا اگه بخوام DataType ی که میسازم وقتی که به عنوان Property در نظر گرفته میشه این فرم رو نشون بده چه باید بکنم؟
یه جورایی مثل System.Windows.Forms.DockStyle که هر پروپرتی که از اون نوع تعریف بشه فرم مربوط به این DataType رو نشون میده
بازهم ممنونم از راهنمایی های کاملتون

همون مساله و همون راه حل ئه، فرقی نکرده، شما یک Enum مثل این رو دارید :
کد:
    Public Enum PowerState
        PowerOff = 0
        PowerOn = 1
    End Enum

و یک Property برای اون :
کد:
    Private _power As PowerState

    Public Property Power() As PowerState
        Get
            Return _power
        End Get
        Set(ByVal value As PowerState)
            _power = value
        End Set
    End Property

و یک UITypeEditor مخصوص همون Enum دارید :
کد:
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
Imports System

Public Class PowerUITypeEditor
    Inherits UITypeEditor

    Public Overrides Function GetEditStyle(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.Drawing.Design.UITypeEditorEditStyle
        Return UITypeEditorEditStyle.Modal
    End Function

    Public Overrides Function EditValue(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal provider As System.IServiceProvider, ByVal value As Object) As Object
        Dim service As IWindowsFormsEditorService = provider.GetService(GetType(IWindowsFormsEditorService))
        If (service Is Nothing) Or (value Is Nothing) Then
            Return value
        End If
        Dim power As MyComponent.PowerState = value
        Using f As New PowerForm
            f.RadioButtonOff.Checked = (power = MyComponent.PowerState.PowerOff)
            f.RadioButtonOn.Checked = (power = MyComponent.PowerState.PowerOn)
            If service.ShowDialog(f) = DialogResult.OK Then
                power = IIf(f.RadioButtonOn.Checked, MyComponent.PowerState.PowerOn, MyComponent.PowerState.PowerOff)
            End If
        End Using
        Return power
    End Function

End Class

حالا شما ابتدای Enum اون دو سطر رو اضافه می کنید :
کد:
[B][COLOR="#0000FF"]    <Editor(GetType(PowerUITypeEditor), GetType(UITypeEditor))> _
    <TypeConverter(GetType(ExpandableObjectConverter))> _
[/COLOR][/B]    Public Enum PowerState
        PowerOff = 0
        PowerOn = 1
    End Enum

و دیگر نیازی به تغییر Property نیست، یعنی برای هر Property ای از اون نوع Enum همون فرم باز میشه.

به مثال پیوستی مراجعه شود :
مشاهده پیوست CustomModalUITypeEditor2.zip
 

ms_vb

Member
واقعا دستت درد نکنه استاد،
خدا خیرت بده
یه سوال دیگه:
اگه متغیر از نوع Structure باشه چیزی که به عنوان مقدار اون Property نشون میده یه متن بی معنیه (CustomModalUITypeEditor.MyComponent+PersonInformation_Struct) چطور میتونم اون رو تغییر بدم؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
واقعا دستت درد نکنه استاد،
خدا خیرت بده
یه سوال دیگه:
اگه متغیر از نوع Structure باشه چیزی که به عنوان مقدار اون Property نشون میده یه متن بی معنیه (CustomModalUITypeEditor.MyComponent+PersonInformation_Struct) چطور میتونم اون رو تغییر بدم؟

هر کلاس و ساختار داده ای به یک ToString متناسب نیاز داره :
کد:
        Public Overrides Function ToString() As String
            Return "Your text"
        End Function
که بهتره با توجه به مقادیر داخل ساختار داده ای تون متنی باشه که مقدار داخل ساختار رو نشون بده.
 

ms_vb

Member
سلام مجدد
حالا یه مشکل دیگه دارم استاد
اونم اینه که وقتی متغیر از نوع Structure تعریف میشه دیگه توی محیط Designer مقدارش ذخیره نمیشه و با یه Rebuild کردن هر مقداری که Set شده باشه از بین میره!:-?
ممنون میشم بگید برای رفع مشکل چی کنم؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن


سلام مجدد
حالا یه مشکل دیگه دارم استاد
اونم اینه که وقتی متغیر از نوع Structure تعریف میشه دیگه توی محیط Designer مقدارش ذخیره نمیشه و با یه Rebuild کردن هر مقداری که Set شده باشه از بین میره!:-?
ممنون میشم بگید برای رفع مشکل چی کنم؟
ثبت شدن داده یک مشخصه به این معنا است که داده داخل اون ساختار Serialize بشه و در کد Resource یا کد فایل Design اون فرم ذخیره بشه.
Designer هر مشخصه ای رو که قابل Serialize کردن باشه به شرط موافقت برنامه نویس ثبت می کنه. پس اولا باید ساختار داده ای قابل Serialize کردن باشه،
یعنی صفت Serializable داشته باشه، ثانیا در تعریف مشخصه با کد نویسی به Designer اعلام کنیم که Serialize اش کنه. در مورد اغلب نوع داده های
استاندارد که مقدار پیشفرض و مقدار دهی شون معلومه این عمل نیازی به تایید نداره اما در مورد یک ساختار داده ای اختصاصی،
Designer نمی تونه همینطوری تصمیم بگیره.

به عنوان مثال یک ساختار داده ای داریم و یک مشخصه که از نوع همین ساختاره :
کد:
[COLOR="#A9A9A9"]    <Editor(GetType(InfoUITypeEditor), GetType(UITypeEditor))> _
[/COLOR]    Public Structure InfoDataType

        Public FirstName As String
        Public LastName As String

    End Structure

    Private _info As New InfoDataType

    Public Property Info() As InfoDataType
        Get
            Return _info
        End Get
        Set(ByVal value As InfoDataType)
            _info = value
        End Set
    End Property

این ساختار داده ای یک Editor اختصاصی با نام InfoUITypeEditor داره که البته ربطی به موضوع Serialize شدن نداره، صرفا
برای این صفت Editor را در کد قرار دادم که برای ترکیب با صفت ای که در ادامه اضافه میشه مثال مناسبی باشه.

ساختار داده ای InfoDataType پیچیدگی خاصی نداره، همچین ساختار هایی بصورت خودکار قابل Serialize شدن هستند اما
Designer این امر را منوط به اجازه برنامه نویس می داند، باید به Designer اعلام کنیم که این ساختار بصورت استاندارد Serialize شدنی است :
کد:
[B][COLOR="#0000FF"]Imports System[/COLOR][/B]
[COLOR="#A9A9A9"].
.
.
[/COLOR][B][COLOR="#0000FF"]    <Serializable()> _[/COLOR][/B]
    <Editor(GetType(InfoUITypeEditor), GetType(UITypeEditor))> _
    Public Structure InfoDataType

        Public FirstName As String
        Public LastName As String

    End Structure

حالا باید شرایطی را تعیین کنیم که مشخصه Info توسط Designer بصورت خودکار Serialize شود. یک قاعده پنهانی برای اینکار وجود دارد که
اگر یک مشخصه با نام XYZ داریم، ShouldSerializeXYZ و ResetXYZ بر اساس منطق Designer به این مشخصه مربوط اند. اولی تعیین می کند که
مشخصه با توجه به مقدار و شرایط فعلی باید Serialize بشود یا نشود و دومی مشخص می کند که مقدار پیشفرض مشخصه چیست
و اگر قرار باشد Reset شود و به مقدار پیشفرض برگردد چه عملیاتی انجام شود.
کد:
[B][COLOR="#0000FF"]    Public Function ShouldSerialize[U]Info[/U]() As Boolean
        Return True
    End Function

    Public Sub Reset[U]Info[/U]()
        Info = New InfoDataType
    End Sub
[/COLOR][/B]
 

ms_vb

Member
خیلی ممنون استاد
خدا خیرت بده، واقعا کارت حرف نداره
یه سوال دیگه
قطعه کد زیر توی خود استراکچر تعریف شه؟
 متغیر Info میتونه Private باشه یا حتما باید Public Property در نظر گرفته بشه؟
کد:
    Public Function ShouldSerializeInfo() As Boolean
        Return True
    End Function

    Public Sub ResetInfo()
        Info = New InfoDataType
    End Sub
میشه یه مثال کامل بزنید؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
خیلی ممنون استاد
خدا خیرت بده، واقعا کارت حرف نداره
یه سوال دیگه
قطعه کد زیر توی خود استراکچر تعریف شه؟
 متغیر Info میتونه Private باشه یا حتما باید Public Property در نظر گرفته بشه؟
کد:
    Public Function ShouldSerializeInfo() As Boolean
        Return True
    End Function

    Public Sub ResetInfo()
        Info = New InfoDataType
    End Sub
میشه یه مثال کامل بزنید؟
نه، ShouldSerialize و Reset جزئی از Structure نیست، کنار Property تعریف میشه، یعنی در اون کلاس (User Control شما) تعریف میشه.

مشخصه ای که Private ئه، صرفا توسط کد های داخلی کلاس قابل دسترسی ئه، از بیرون کلاس دیده نمیشه، پس بنابر این Designer یک فرم
نه همچین مشخصه ای رو می بینه و نه بهش دسترسی داره که بخواد Serialize اش بکنه و طبعا مقدارش توسط Designer ویژوال استدیو ذخیره نخواهد شد.

کد:
Public Class Component1
    Private _backColor As Color

    Public Property [B][COLOR="#0000FF"]BackColor[/COLOR][/B]() As Color
        Get
            Return IIf(_backColor.IsEmpty, Color.Blue, _backColor)
        End Get
        Set(ByVal value As Color)
            _backColor = value
        End Set
    End Property

    Public Function ShouldSerialize[B][COLOR="#0000FF"]BackColor[/COLOR][/B]() As Boolean
        Return ([B][COLOR="#0000FF"]BackColor[/COLOR][/B] <> Color.Blue)
    End Function

    Public Sub Reset[B][COLOR="#0000FF"]BackColor[/COLOR][/B]()
        [B][COLOR="#0000FF"]BackColor[/COLOR][/B] = Color.Blue
    End Sub
End Class

اگر یک نمونه از این Component1 را روی فرم قرار دهید، رنگ پیشفرض BackColor اش Blue است، در پنجره Properties اتفاقات زیر می افتد :
اگر BackColor هر مقداری غیر از Blue داشته باشد فونت ای که برای نمایش مقدارش بکار برده می شود Bold خواهد بود.
اگر در پنجره Properties روی مشخصه BackColor راست کلیک شود و گزینه Reset انتخاب شود به رنگ Blue بر می گردد.
 

جدیدترین ارسال ها

بالا