2016-12-08 5 views
-1

У меня есть ListView с циклом для заполнения элементов, каждый элемент создается есть экземпляр класса TSMPPConnection и этот класс свойство ConnectionItem держать элемент ListView, я хочу изменить пункт текст из внутренний класс, запрос которого поступает из объектного события, когда я изменяю текст элемента напрямую, он генерирует исключение.Делегатов в пределах класса

Дополнительная информация: операция Cross-нить не действует: Control «lstConnections» доступ из другого потока, чем нить она была создана.

Делегаты: я использовал делегат для достижения этой, но ту же ошибку.

Delegate Sub dlg_WriteConnectionItemStatus(s As String) 
    Sub WriteConnectionItemStatus(s As String) 

     Dim dlg As New dlg_WriteConnectionItemStatus(AddressOf WriteConnectionItemStatus) 
     dlg.Invoke(s) 

     'there is no InvokeRequired to check if execution come from delgate and avoid infinite loop 
     If ConnectionItem IsNot Nothing Then ConnectionItem.SubItems(6).Text = s 

    End Sub 

Там нет InvokeRequired, чтобы проверить исполнение приходят от делегата и избежать бесконечного цикла

Попробуйте 1: Использование другого суб с такой же структурой, чтобы вызвать его из делегатом внутри оригинальной суб.

Delegate Sub dlg_WriteConnectionItemStatus(s As String) 
    Sub WriteConnectionItemStatus(s As String) 

     Dim dlg As New dlg_WriteConnectionItemStatus(AddressOf WriteConnectionItemStatus_Interface) 
     dlg.Invoke(s) 

    End Sub 

    Sub WriteConnectionItemStatus_Interface(s As String) 

     If ConnectionItem IsNot Nothing Then ConnectionItem.SubItems(6).Text = s 

    End Sub 

ЖЕ ОШИБКА

ответ

1

Вы должны вызвать элемент управления или форму, вызов делегата сам равно просто назвав его непосредственно: WriteConnectionItemStatus().

Вы можете упростить путем создания метода расширения для этого вместо:

Imports System.Runtime.CompilerServices 

Public Module Extensions 
    <Extension()> _ 
    Public Sub InvokeIfRequired(ByVal Control As Control, ByVal Method As Action) 
     If Control.InvokeRequired = True Then 
      Control.Invoke(Method) 
     Else 
      Method.Invoke() 
     End If 
    End Sub 
End Module 

Чтобы использовать его, вы должны получить родительскую ListView элемента. Если вы ориентируетесь .NET 4.0 или выше вы можете использовать лямбда-выражения вместо нормальных делегатов, что проще писать и гораздо более гибкими:

Sub WriteConnectionItemStatus(s As String) 

    If ConnectionItem IsNot Nothing Then _ 
     ConnectionItem.ListView.InvokeIfRequired(Sub() ConnectionItem.SubItems(6).Text = s) 
End Sub 

Однако, если вы ориентируетесь .NET 3.5 или ниже вы должны придерживаться делегатов:

Delegate Sub SetSubItemTextDelegate(Item As ListViewItem, Index As Integer, Text As String) 

Sub WriteConnectionItemStatus(s As String) 

    If ConnectionItem IsNot Nothing Then _ 
     ConnectionItem.ListView.InvokeIfRequired(New SetSubItemTextDelegate(AddressOf SetSubItemText), ConnectionItem, 6, s) 
End Sub 

Sub SetSubItemText(Item As ListViewItem, Index As Integer, Text As String) 'Generalized method for flexibility. 
    Item.SubItems(Index).Text = Text 
End Sub 
+0

большое спасибо моя проблема решена :); – Realbitt

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