Problem with binding child controls of a User Control to UC's public property

前端 未结 1 1205
情深已故
情深已故 2020-12-22 04:04
  1. I created a UserControl with a public property of my custom class as described below, with the purpose of editing instances of my custom class
  2. I attempted t
相关标签:
1条回答
  • 2020-12-22 05:07

    Here's a sample UserControl with some Controls bound to the properties of a public class object (JobDefinition). The public class is part of the Project classes.
    A property of this class is an Enumerator - JobStatusEnum - used to further test how the public property works when the class object is decorated with a TypeConverter attribute.

    The public JobDefinition class uses a TypeConverter of type ExpandableObjectConverter, to allow the editing of the UserControl Property of type JobDefinition.

    This class also implements the INotifyPropertyChanged interface, commonly used to notify binding clients that a Property value has changed, raising a PropertyChanged event.

    A BindingSource is then used to bind some of the UC's Controls to a Property of the JobDefinition class, setting the DataSource of the BindingSource to the UserControl's public Job property.

    All the Controls' Bindings are added in the UserControl's OnLoad method override, calling the BindControls() method.

    Edit:
    If you don't want/need to have active bindings when a new instance of the UserControl is created, you can set the BindingSource's DataSource property to the object type that will generate the source of the data, without specifying an instance of that object.

    BindingSource.DataSource:

    The DataSource property can be set to a number of data sources, including types, objects, and lists of types. The resulting data source will be exposed as a list.

    In this case, the initialization procedure of the UserControl can be changed in:

    Public Sub New()
        InitializeComponent()
        m_Source = New BindingSource() With {.DataSource = GetType(JobDefinition)}
    End Sub
    

    The UserControl's child controls will show empty at Design-Time and the Job property, though listed in the Designer's PropertyGrid, will also be empty.
    It can set to a new object at any time.


    At Design-Time, the UC's JobDefinition property type can be set to any value. These setting will be preserved when the Form is loaded, since the class is serialized by the Designer.
    All bound Controls will react to the Property changes and the new values will be reflected in the UI at Design-Time.

    At Run-Time, all properties can of course be set to different values: the UI and the UserControl's Properties will reflect the new values.

    The Property of type JobDefinition can also be set to a new, different object. The BindingSource will take care of the bound Control's DataBindings, updating the properties when its DataSource is changed.

    Private Sub btnJobChangeValue_Click(sender As Object, e As EventArgs) Handles btnJobChangeValue.Click
        MyUserControl1.Job.JobName = txtNewJobName.Text
    End Sub
    
    Private Sub btnNewJob_Click(sender As Object, e As EventArgs) Handles btnNewJob.Click
        Dim newJob = New JobDefinition() With {
            .JobID = 5, 
            .JobName = "New Job", 
            .JobStatus = JobStatusEnum.Starting
        }
        MyUserControl1.Job = newJob
    End Sub
    

    The sample UserControl:

    Imports System.ComponentModel
    Imports System.Windows.Forms
    
    Partial Public Class MyUserControl
        Inherits UserControl
    
        Private m_Job As JobDefinition = Nothing
        Private m_Source As BindingSource = Nothing
    
        Public Sub New()
            InitializeComponent()
            m_Source = New BindingSource()
            Me.Job = New JobDefinition() With {
                .JobID = 1, 
                .JobName = "Initial Job", 
                .JobStatus = JobStatusEnum.Starting
            }
        End Sub
    
        Public Property Job As JobDefinition
            Get
                Return m_Job
            End Get
            Set(ByVal value As JobDefinition)
                m_Job = value
                m_Source.DataSource = m_Job
            End Set
        End Property
    
        Protected Overrides Sub OnLoad(e As EventArgs)
            MyBase.OnLoad(e)
            BindControls()
        End Sub
    
        Friend Sub BindControls()
            txtJobID.DataBindings.Add(New Binding("Text", m_Source, "JobID", False, DataSourceUpdateMode.OnPropertyChanged))
            txtJobName.DataBindings.Add(New Binding("Text", m_Source, "JobName", False, DataSourceUpdateMode.OnPropertyChanged))
            txtJobStatus.DataBindings.Add(New Binding("Text", m_Source, "JobStatus", False, DataSourceUpdateMode.OnPropertyChanged))
        End Sub
    End Class
    

    JobDefinition class object:

    Imports System.ComponentModel
    
    <TypeConverter(GetType(ExpandableObjectConverter))>
    Public Class JobDefinition
        Implements INotifyPropertyChanged
    
        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    
        Private m_JobID As Integer
        Private m_JobName As String
        Private m_JobStatus As JobStatusEnum
    
        Public Property JobID As Integer
            Get
                Return m_JobID
            End Get
            Set(ByVal value As Integer)
                m_JobID = value
                OnPropertyChanged(NameOf(Me.JobID))
            End Set
        End Property
    
        Public Property JobName As String
            Get
                Return m_JobName
            End Get
            Set(ByVal value As String)
                m_JobName = value
                OnPropertyChanged(NameOf(Me.JobName))
            End Set
        End Property
    
        Public Property JobStatus As JobStatusEnum
            Get
                Return m_JobStatus
            End Get
            Set(ByVal value As JobStatusEnum)
                m_JobStatus = value
                OnPropertyChanged(NameOf(Me.JobStatus))
            End Set
        End Property
    
        Friend Sub OnPropertyChanged(PropertyName As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(PropertyName))
        End Sub
    End Class
    

    The JobStatusEnum enumerator:

    Public Enum JobStatusEnum As Integer
        Starting
        Started
        Pending
        Stopped
        Completed
    End Enum
    

    Downloadable Project (Google Drive)
    The Obj folder is empty, so rebuild the Solution before opening the Form or the UserControl in the Form's Designer.

    0 讨论(0)
提交回复
热议问题