Каким образом передавать в Property больше 1 значения?
Пишу свой грид (все известные мне гриды (TrueDbGrid, MSFlexGrid, ListViev и т.д.) не удовлетворяют различным требованиям, предъявляемым мною для решения одной задачки). Описал столбец для него. Столбцы выкладываю на другой контрол, который и будет являться гридом.
Мне необходимо задавать стили отображения для столбцов, такие как ширина, размеры шрифтов, стиль, ответственный за то, что будет отображаться в столбце (каждый столбец может отображать разные элементы управления) и т.п.
Я уже писал подобный грид (только он был несколько ограниченным). В него стиль для столбца передавался через Public Sub. Т.е., например:
Т.е. передаётся, как видите, индекс столбца и стиль его отображения.
Данная структура очень удобна и проста в реализации, но в случае, если я передаю стиль столбца через Property, я могу при разработке проекта, выложив контрол на форму, задать в свойствах контрола все стили для всех столбцов и наглядно посмотреть, что получается. Если использую процедуру (Sub), то этого уже добиться нельзя. Кирме того, если работать через Propery, то гораздо легче из кода обрабатывать (получать и передавать) различные значения для контрола. Например, если есть структура:
Тыры-пыры
End Property
Public Property Get ColumnStyle() As Long
ColumnStyle = Column.Style
Тыры-пыры
End Property
то я могу из кода обращаться к ней:
B = МойКонтрол.ColumnStyle
А если есть структура:
Тыры-пыры
End Property
Public Function RetColumnStyle(ByVal ColIndex As Long) As Long
Тыры-пыры
RetColumnStyle = Column(ColIndex).Style
End Property
то я при обращении из кода должен использовать:
C = МойКонтрол.RetColumnStyle(A)
что не так удобно, так как нужно помнить имена процедур (понимаете, когда много свойств, даже если процедуры обозваны понятно, всё равно возникает "запарка")
Можно, конечно, реализовать отдельную настройку столбцов, как это сделано у всех гридов, но это - дополнительный довесок и время, которое поджимает. К тому же это не снимает вторую проблему (с именованием).
Поэтому мне желательно это дело реаливывать через Property, но Property "по умолчанию" позволяет передавать и возвращать только 1 свойство. И структура:
Тыры-пыры
End Property
Public Property Get ColumnStyle(ByVal ColIndex as long) As Long
ColumnStyle = Column(ColIndex).Style
Тыры-пыры
End Property
"не прокатывает".
Кто-нибудь знает, возможно ли вообще, и, если возможно, то как, это обойти?
Ведь свойство токо выглядит как функция, но ее вызов же идет в коде, так:
Dim a as MyClass
Set a = New MyClass
a.Text = "dfsfs"
т.е. ты пишешь Объект.Свойство и дальше равно "=", а после "=" не может следовать несколько значений .
Кроме как описаных тобой методы (написать не свойство Text, а метод - SetText(,)) я больше не вижу. Тем более я не представляю все равно как станд. инспектор свойств сможет отобразить такое свойство - тут все равно понадобится Построитель, например как для Color'а.
Что мне приходит в голову.
Можно забить твои свойства прям в класс по типу:
Col1 As Long
Style1 As Long
Col2 As Long
Style2 As Long
Col3 As Long
Style3 As Long
......
и т.д.
Сотв. нарожать стоко же Property Get/Let, а тебе в классе придется следить за ними и заполнять эти переменные, чтобы они всегда соотвествовали реальному положению дел. Недостатки - выглядеть код будет прикольно :)
Вариант 2: Нельзя передать больше одной переменной в Property, но можно передать структуру, массив. Тогда тебе придется сначала в коде создавать массив/структуру и потом уже его присваивать свойству:
a.Text = myType/myArray
По определению Property - только одно свойство. Единственный выход, что вижу - делать несколько независимых свойств. Но по мне, лучше все-таки функцию определить, а не свойства.
Ладно, что уж поделать...:{
Тем более, что я уже начал через процедуры и функции енто делать...
А, кстати, немного не понял насчёт массива... Можно поподробнее? Приблизительный код, например?:P
Public Property Let ds(a1 As String, a2 As String, s1 As String)
If a1 = "sd" And a2 = "dsf" Then
s = s1
End If
End Property
Public Property Get ds(a1 As String, a2 As String) As String
ds = s
End Property
Т.е. как значение для свойства будет браться последний аргумент в Let, т.е. именно он то и будет стоять после "=". А вот остальные (a1 и a2) будут играть роль вспомогательных и они должны быть идентичными что у Let, то и у Get - иначе не откомпиллируется.
Т.е. вид будет такой:
Set a = New Class1
a.ds("sdf", "sfsd") = "fddsf"
Public Property Let ds(Optional a1 As String = "111", Optional a2 As String = "222", s1 As String)
и тогда мона писать как хочется:
Set a = New Class1
a.ds("sfs","ssd") = "sdfsd"
или так
a.ds = "sdfsd" - что уже очень приятно
Ну и также кроме обычных переменных мона еще и массивы сувать:
..... Let ds(ParamArray a1() As String,.....
Да, чуть не забыл, можно же еще эти параметры как Optional объявлять:
Public Property Let ds(Optional a1 As String = "111", Optional a2 As String = "222", s1 As String)
и тогда мона писать как хочется:
Set a = New Class1
a.ds("sfs","ssd") = "sdfsd"
или так
a.ds = "sdfsd" - что уже очень приятно
Ну и также кроме обычных переменных мона еще и массивы сувать:
..... Let ds(ParamArray a1() As String,.....
Простите за просто идиотский вопрос (возможно, меня от упорного труда вновь клинит), но как узнать размерность массива? Хотя бы его верхнюю границу?P(
Простите за просто идиотский вопрос (возможно, меня от упорного труда вновь клинит), но как узнать размерность массива? Хотя бы его верхнюю границу?P(
Dim mas(1 To 10) as String
верхн. UBound(mas)
нижн. LBound(mas)
Делай свойство типа Variant и передавай туда что пожелаешь, хоть массив, хоть свой тип данных.
Большое спасибо!
Но у меня проблема поинтереснее. Так как мне нужно передавать массив для заполнения комбобокса, то я передаю в него 2-х мерный массив. А вот как определить его размерность?
Большое спасибо!
Но у меня проблема поинтереснее. Так как мне нужно передавать массив для заполнения комбобокса, то я передаю в него 2-х мерный массив. А вот как определить его размерность?
И ещё один вопрос. Можно ли создавать коллекцию массивов в массиве. Тоесть, очень заманчиво заполнять грид целиком из массива. В основном проекте формировать массив, а потом передавать его гриду, а тот уж пусть сам себя из массива заполняет. Но так как в гриде есть комбобоксы, то их данные прийдётся, в свою очередь, хранить в массивах. Поэтому получится ли "запихнуть" массив в массив?
Большое спасибо!
Но у меня проблема поинтереснее. Так как мне нужно передавать массив для заполнения комбобокса, то я передаю в него 2-х мерный массив. А вот как определить его размерность?
Наскоко мне известно встроенной функции для определения размерности массива нет, поэтому как вариант я накатал следующую функцию:
Dim i As Long, k As Long
On Error GoTo Er_
RazmMassive = 0
Do
i = i + 1
k = UBound(mas, i)
Loop Until i = 1000
Ex_:
Exit Function
Er_:
If Err.Number = 9 Then ' Error - Subscript out of range
RazmMassive = i - 1
Else
MsgBox Err.Description
End If
Resume Ex_
End Function
Принцип очень простой, мы просто пытаемся определить верхн. границу каждой размерности по очереди, пока не получим ошибку №9 - Subscript out of range
P.S. функция обламается, если в опциях компилляции отказатся от установленного по умолч. опции - проверка индекса на выход из массива
Dim a() As Variant
Dim k As Variant
ReDim a(3)
k = a
ReDim a(2)
k(0) = a
k(1) = a
k(2) = a
k(3) = a
End Sub
Перед выходом посмотри значение к. Обращание к элементам типа к(1)(3)(4. В любой элемент можно запихать сколько угодно вложенных массивов и контроль наличия массива легко определить.
Sub Sample()
Dim a() As Variant
Dim k As Variant
ReDim a(3)
k = a
ReDim a(2)
k(0) = a
k(1) = a
k(2) = a
k(3) = a
End Sub
Перед выходом посмотри значение к. Обращание к элементам типа к(1)(3)(4. В любой элемент можно запихать сколько угодно вложенных массивов и контроль наличия массива легко определить.
О, огромное спасибо!
Обязательно постараюсь в ближайшее время вклюсить это в код грида (правда, теперь уже в следующую версию, к сохалению - эту уже сегодня буду подключать к проекту)