2013-08-30 2 views
0

Каков наилучший метод для ссылки на класс для пользовательской формы?Ссылка на объект с пользовательским интерфейсом

Извините, что являюсь гипотетическим, но с использованием фактического кода будет возникать вопрос, который длится страницы.

Предположим, у меня есть класс, содержащий данные о человеке.

<<class Person>> 
Public FirstName as String 
Public LastName as String 
Public PhoneNumber as String 
<<end class>> 

Я поместил эти данные в список просмотров VBA UserForm.

Теперь предположим, что я хочу изменить номер телефона на 555-555-1234, если пользователь нажимает на эту запись в списке.

Я могу прочитать взаимодействие со списком с событием click элемента.

Private Sub lvExample_ItemClick(ByVal Item As MSComctlLib.ListItem) 
    ' Change the phone number 
End Sub 

Каков наилучший способ добраться от предмета в приведенном выше коде к моему фактическому объекту? Должен ли я добавить GUID для каждого объекта и поместить его в тег списка, а затем посмотреть его? Должен ли я добавить listitem из списка в класс, чтобы я мог перемещаться по всем моим людям, а затем увидеть, является ли Item из _ItemClick равным Item из объекта?

+1

Добавление идентификатора GUID - это хороший способ, или любой другой идентификатор, позволяющий однозначно идентифицировать объект отдельного человека. В вашем примере номер телефона может быть уникальным для каждого человека и способен действовать как идентификатор. Это не сработает, если вы ожидаете когда-либо более одного номера телефона человеку или нескольким лицам по номеру телефона. – jac

+0

Сохранены ли ваши данные на листе Excel, базе данных Access или просто в списке Word? Откуда появляется информация Лица? – tigeravatar

+0

Данные в этом случае загружаются из SQL. – lfrandom

ответ

3

Самый простой способ - использовать свойство Index, если у вас нет уникального идентификатора или свойства Key, если вы делаете, ListItem.

Если вы решите использовать свойство Index, то вы не сможете (или, по крайней мере, сильно усложнить его) добавить любую функциональность, чтобы изменить порядок элементов списка.

Вы бы заполнили ListView на основе объектов в коллекции/наборах записей с помощью метода ListView.ListItems.Add. Свойство Index можно использовать для возврата к этому исходному объекту в зависимости от порядка элементов в ListItems, соответствующих порядку элементов в исходной коллекции объектов.

В качестве альтернативы, если вы предпочитаете большую гибкость при использовании уникального ключа, но не хотите изменять базовый объект, то вы можете тривиально построить уникальный ключ (самым простым из которых является CStr (некоторое увеличивающееся число)) по мере добавления каждый объект в ListItems, сохраняя ключи вместе с объектами.

Затем вы можете использовать свойство .Key для ListItem. Преимущество здесь в том, что пользователю разрешено изменять элементы, удалять файлы и т. Д., Без необходимости аннулировать ваш контроль и повторно добавлять все объекты, чтобы сохранить связь между индексом в источнике и индексом в списке.

Например:

Private persons As Collection 
Private Sub lvExample_ItemClick(ByVal Item As MSComctlLib.ListItem) 
    ' Change the phone number: 

    'Method 1, using the index of listitem within listitems 
    'to tie back to index in persons collection 
    'Don't allow rearranging/sorting of items with this method for simplicity 
    With persons.Item(Item.Index) 
     .PhoneNumber = "555-555-1234" 
     '...some stuff 
    End With 

    'Method 2, using a unique key 
    'that you generate, as the underlying person object doesn't have a necessarily unique one 
    'Items would have been added in a method similar to AddItemsExample1() below 
    With persons.Item(Item.Key) 
     .PhoneNumber = "555-555-1234" 
     '...some stuff 
    End With 


End Sub 

Sub AddItemsExample1() 
    'Storage requirements vs. your existing recordset or whatever 
    'are minimal as all it is storing is the reference to the underlying 
    'person object 

    'Adapt per how you have your existing objects 
    'But basically get them into a keyed collection/dictionary 

    Dim i As Long   
    Set persons = New Collection 
    For Each p In MyPersonsSource 
     persons.Add p, CStr(i) 
     i = i + 1 
    Next p 

    'By keying them up, you can allow sorting/rearranging 
    'of the list items as you won't be working off of Index position 

End Sub 

Наконец, еще один способ, если у вас есть их в наборе записей, возвращенных БД, чтобы добавить новое поле (я полагаю, у вас есть существующее поле объекта) и не выполнить запрос UPDATE на ваших записях, заполняющих его инкрементирующим числом (это должно влиять только на местный набор записей (сначала проверьте настройки набора записей!)). Используйте это как ключ.

Вы упомянули в комментарии к своему вопросу о том, что вы получаете данные из SQL. Для всех нормальных целей с помощью окна списка все же, вероятно, проще всего запустить их через объект Collection, как описано выше, но если у вас есть, например, 4 поля из SQL для записи в наборе записей, тогда у вас нет «объекта» в смысле возможности называть свойства на нем.Пожалуйста, укажите в своем вопросе или в комментарии к этому, если вы это сделаете, так как может быть лучшее лечение для ответа на ваш вопрос или фактическая операция обновления, скорее всего, потребует различного синтаксиса или семантики (особенно если вам необходимо распространить любое обновление на источник) :)

+0

+1 хорошие ответы на очень нечеткий и широкий вопрос. –

+0

@mehow, я согласен, что вопрос широк, но это целеустремленно, я спрашиваю, есть ли лучший способ что-то сделать. Я был бы признателен за конструктивную критику в отношении того, как улучшить этот вопрос. – lfrandom

+0

@ Не важно, как у вас есть «люди»? Я предполагаю, что у вас есть соответствующие «объекты», когда вы упоминаете человека класса, так что это полезно, и я полагаю, что обновление БД выходит за рамки вопроса. В любом случае, помогли ли какие-либо мои предложения? Если нет, скажите, почему не для моей справки. Спасибо –

0

Я бы использовал подход, управляемый событиями.

Person будет иметь свойства вместо переменных, и присвоение этих свойств вызовет событие.

Форма пользователя будет иметь WithEvents Person, так что изменения в связанных лицах вызывают код пользовательской формы.

Person класс:

Public Event Changed() 
Private pFirstName As String 
Private pLastName As String 
Private pPhoneNumber As String 

Public Property Get FirstName() As String 
    FirstName = pFirstName 
End Property 

Public Property Let FirstName(ByVal v As String) 
    pFirstName = v 
    RaiseEvent Changed 
End Property 

Public Property Get LastName() As String 
    LastName = pLastName 
End Property 

Public Property Let LastName(ByVal v As String) 
    pLastName = v 
    RaiseEvent Changed 
End Property 

Public Property Get PhoneNumber() As String 
    PhoneNumber = pPhoneNumber 
End Property 

Public Property Let PhoneNumber(ByVal v As String) 
    pPhoneNumber = v 
    RaiseEvent Changed 
End Property 

Событие ловли в форме пользователя:

Public WithEvents ThisPerson As Person 

Private Sub ThisPerson_Changed() 
    'Update user form 
End Sub 

Поэтому, когда вы назначаете YourForm.RelatedObject = SomePerson, любые изменения, сделанные в SomePerson будут вызывать код в YourForm.

0

Поскольку вы не можете изменить вернулись ListItem, у меня есть еще одно решение:

Добавить связанный ListItem ваших Person класса:

Public FirstName as String 
Public LastName as String 
Public PhoneNumber as String 
Public RelatedObject As Object 

При заполнении TreeView, назначьте его:

Set SomeListItem = SomeTreeView.ListItems.Add(...) 
Set SomePerson.RelatedObject = SomeListItems 

Поэтому всякий раз, когда вы вносите изменения в ListItem:

Private Sub SomeListView_ItemClick(ByVal Item As MSComctlLib.ListItem) 
    Dim p As Person 
    For Each p In (...) 
     If p.RelatedObject Is Item Then 
      'Found, p is your person! 
      p.PhoneNumber = ... 
     End If 
    Next 
End Sub 

В качестве альтернативы, если вы не хотите, чтобы изменить свой Person класс, вы можете оформить его в другом классе, например, PersonToObject:

Public Person As Person 
Public RelatedObject As Object 

И использовать PersonToObject в качестве объектов связи.

Смежные вопросы