Контрол, производный от ListBox. Отображение элементов Items
От: enabokov  
Дата: 19.03.08 07:54
Оценка:
Создал свой контрол RangeListBox, производный от ListBox. Переопределил свойство Items: был ObjectCollection, стал RangeList.
Теперь элементы Items не отображаются в моём RangeListBox. RangeList -- коллекция RangeItem'ов, у которых я реализовал функцию ToString().
В дизайнере форм в редакторе свойства Items эти элементы вводятся и отображаются как надо, но на самой форме -- нет. Что нужно сделать, чтобы они отображались? Проект на VB.NET.
Re: Исходник контрола.
От: enabokov  
Дата: 20.03.08 07:10
Оценка:
Вот мой опус.
Imports System
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Collections.Generic

Public Class RangeListBox
    Inherits ListBox

    Private _minValue As Integer
    Private _maxValue As Integer
    Private _items As RangeList
    Private Const defaultMinValue As Integer = 0
    Private Const defaultMaxValue As Integer = 999999

    Public Sub New()
        MyBase.New()
        _items = New RangeList()
        _minValue = defaultMinValue
        _maxValue = defaultMaxValue
    End Sub

    <DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible), _
    DescriptionAttribute("Min value of range."), CategoryAttribute("Constraints"), _
    DefaultValue(defaultMinValue), BrowsableAttribute(True), LocalizableAttribute(False)> _
    Public Property MinValue() As Integer
        Get
            Return _minValue
        End Get
        Set(ByVal value As Integer)
            If value > _minValue Then
                Throw New MaxLessMinException("Минимальное значение должно быть меньше или равно максимальному.")
                ' TODO: В режиме дизана формы не генерировать исключение.
            Else
                _maxValue = value
            End If
        End Set
    End Property

    <DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible), _
    DescriptionAttribute("Max value of range."), CategoryAttribute("Constraints"), _
    DefaultValue(defaultMaxValue), BrowsableAttribute(True), LocalizableAttribute(False)> _
    Public Property MaxValue() As Integer
        Get
            Return _maxValue
        End Get
        Set(ByVal value As Integer)
            If value < _minValue Then
                Throw New MaxLessMinException("Максимальное значение должно быть больше или равно минимальному.")
                ' TODO: В режиме дизана формы не генерировать исключение.
            Else
                _maxValue = value
            End If
        End Set
    End Property

    <LocalizableAttribute(True)> _
    Public Shadows ReadOnly Property Items() As RangeList
        Get
            Return _items
        End Get
    End Property
End Class    ' RangeListBox

Public Class RangeList
    Inherits CollectionBase
'Inherits ListBox.ObjectCollection

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal Capacity As Integer)
        MyBase.New(Capacity)
    End Sub

    Public Shadows Function Add(ByVal value As RangeItem) As Integer
        'Insert(Count, value)
        'Return Count
        Return List.Add(value)
    End Function 'Add

    Default Public Property Item(ByVal index As Integer) As RangeItem
        Get
            Return CType(List(index), RangeItem)
        End Get
        Set(ByVal value As RangeItem)
            List(index) = value
        End Set
    End Property

    Public Shadows Sub Insert(ByVal index As Integer, ByVal value As RangeItem)
        'Dim ExistentItemIndex As Integer = List.IndexOf(value)
        '' Не допустим пересечения диапазонов.
        '' TODO: реализовать опциональность такого поведения.
        'If ExistentItemIndex > -1 Then
        '    Dim ExistentRangeItem As RangeItem
        '    ExistentRangeItem = CType(Item(ExistentItemIndex), RangeItem)
        '    ' Манипуляции с проверкой на существование/перекрытие/вхождение с выводом соответствующих сообщений
        '    If value.IsOneNumber Then
        '        If ExistentRangeItem.IsOneNumber Then
        '            Throw New RangesIntersectionException("Номер уже присутствует в списке.")
        '        Else
        '            Throw New RangesIntersectionException("Номер входит в диапазон, присутствующий в списке.")
        '        End If
        '    Else
        '        If ExistentRangeItem.IsOneNumber Then
        '            Throw New RangesIntersectionException("В списке присутствует один или несколько номеров, принадлежащих диапазону.")
        '        Else
        '            If value.BottomValue = ExistentRangeItem.BottomValue And value.TopValue = ExistentRangeItem.TopValue Then
        '                Throw New RangesIntersectionException("Диапазон уже присутствует в списке.")
        '            Else
        '                Throw New RangesIntersectionException("Диапазон пересекается с присутствущим в списке.")
        '            End If
        '        End If
        '    End If
        'End If
        List.Insert(index, value)
    End Sub    'Insert

    'Public Property AllowIntersection() As Boolean
    '    Get
    '        Return _allowIntersection
    '    End Get
    '    Set(ByVal value As Boolean)
    '        If Not value AndAlso List.Count > 0 Then
    '            'Throw New RangesIntersectionException("")
    '            'TODO: сделать интеллектуальное изменение свойства.
    '        End If
    '        _allowIntersection = value
    '    End Set
    'End Property
        'Private _allowIntersection As Boolean
End Class    ' RangeList

Public Class RangeItem
    Inherits Object

    Sub New()
        MyBase.New()
        _bottomValue = 0
        _topValue = 0
    End Sub

    Sub New(ByVal Value As RangeItem)
        MyBase.New()
        _bottomValue = Value.BottomValue
        _topValue = Value.TopValue
    End Sub

    Sub New(ByVal Value As Integer)
        MyBase.New()
        _bottomValue = Value
        _topValue = Value
    End Sub

    Sub New(ByVal BottomValue As Integer, ByVal TopValue As Integer)
        MyBase.New()
        _bottomValue = BottomValue
        _topValue = TopValue
    End Sub

    Public Property BottomValue() As Integer
        Get
            Return _bottomValue
        End Get
        Set(ByVal value As Integer)
            If value > _topValue Then
                Throw New MaxLessMinException("Нижнее значение диапазона должно быть меньше верхнего.")
            Else
                _bottomValue = value
            End If
        End Set
    End Property

    Public Property TopValue() As Integer
        Get
            Return _topValue
        End Get
        Set(ByVal value As Integer)
            If value < _bottomValue Then
                Throw New MaxLessMinException("Верхнее значение диапазона должно быть больше нижнего.")
            Else
                _topValue = value
            End If
        End Set
    End Property

    Public ReadOnly Property IsOneNumber() As Boolean
        Get
            Return Me.BottomValue = Me.TopValue
        End Get
    End Property

    Public Overrides Function ToString() As String
        If IsOneNumber Then
            Return Convert.ToString(BottomValue)
        Else
            Return Convert.ToString(BottomValue & "-" & TopValue)
        End If
    End Function

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        ' Check for null values and compare run-time types.
        If obj Is Nothing Then
            Return False
        Else
            If Not Me.GetType() Is obj.GetType() Then
                Return False
            End If
        End If

        Dim OtherRangeItem As RangeItem = CType(obj, RangeItem)
        ' Проведём сложную провеку, суть которой в том чтобы выявить
        ' 1) если введён номер, то есть ли уже он в списке или входит в какой-либо диапазон из списка;
        ' 2) если введён диапазон номеров, то есть ли уже он в списке или есть в списке номера/диапазоны номеров которые пересекаются с ним.
        Return (Me.IsOneNumber And OtherRangeItem.IsOneNumber And Me.BottomValue = OtherRangeItem.BottomValue) Or _
        (Me.IsOneNumber And Not OtherRangeItem.IsOneNumber And Me.BottomValue >= OtherRangeItem.BottomValue And Me.BottomValue <= OtherRangeItem.TopValue) Or _
        (Not Me.IsOneNumber And OtherRangeItem.IsOneNumber And OtherRangeItem.BottomValue >= Me.BottomValue And OtherRangeItem.BottomValue <= Me.TopValue) Or _
        (Not Me.IsOneNumber And Not OtherRangeItem.IsOneNumber And Me.BottomValue <= OtherRangeItem.TopValue And Me.TopValue >= OtherRangeItem.BottomValue)
    End Function

    Private _topValue As Integer
    Private _bottomValue As Integer
End Class    ' RangeItem

' Мои исключения.
Public Class MaxLessMinException
    Inherits ArgumentOutOfRangeException

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal Message As String)
        MyBase.New(Message)
    End Sub

    Public Sub New(ByVal Message As String, ByVal InnerEx As Exception)
        MyBase.New(Message, InnerEx)
    End Sub
End Class    ' MaxLessMinException

Public Class RangesIntersectionException
    Inherits InvalidOperationException

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal Message As String)
        MyBase.New(Message)
    End Sub

    Public Sub New(ByVal Message As String, ByVal InnerEx As Exception)
        MyBase.New(Message, InnerEx)
    End Sub
End Class    'RangesIntersectionException
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.