0

对于任何可以帮助或向我展示更好方法的人。我尝试使用可观察的集合、基于自定义类的列表、全局/非全局集合、使用列表框的 itemssource、同步锁定,最后清空并手动输入项目来做到这一点。

它往往工作正常,但每隔一段时间我就会收到错误“集合已修改;枚举操作可能无法执行”。这似乎发生在 System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()

在过去的几周里,我尝试了一些不同的事情,有时我可以避免它,但我可以在不同的区域重现它。

本质上,我有三个列表框 Parent、Current、Children。这些都有标题图像。选择图像后,父、当前和子中的图像将清空并根据所选图像重新加载。

我已经用 vb 编写了它,但如果有帮助的话,我可以将它转换为 C#。代码已更改多次,因此最新的代码中有很多注释代码。任何帮助或建议将不胜感激。任何简化它、让它工作或性能增强的东西都会很棒。

想象一下一式三份的代码。除了名称之外,代码几乎相同。

<Page.Resources>

    <CollectionViewSource
          Source="{Binding Source={x:Static Application.Current}, Path=CurrentList}"   
          x:Key="CurrentList" />

</Page.Resources>

<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Disabled"    PanningMode="VerticalOnly" FlowDirection="RightToLeft" HorizontalScrollBarVisibility="Auto"
                  >
                <ListBox Name="CurrentListbox" VerticalAlignment ="Stretch" Margin=" 8" Background="Transparent" 
                          Height="Auto"   BorderThickness="0" HorizontalContentAlignment="Center" FlowDirection="LeftToRight" HorizontalAlignment="Center"
                         ItemsSource="{Binding CurrentList}">
                    <ListBox.Resources>
                        <Style TargetType="{x:Type ListBoxItem}">
                            <EventSetter Event="ListBoxItem.Selected" Handler="CurrentListBoxItem_Selected" HandledEventsToo="false"/>
                </Style>
                        </ListBox.Resources>
                    <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel IsItemsHost="True" />
                </ItemsPanelTemplate>
                        </ListBox.ItemsPanel>
                    <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="#FF0000AC" Style="{StaticResource ResourceKey=ThumbnailBorder}">
                        <!--<Viewbox MaxWidth ="100" >-->
                        <StackPanel>

                            <Grid>
                                <Border  Name="ItemBorder" Style="{StaticResource ResourceKey=ThumbnailInnerBorder}"/>
                                <Image Name="PersonImage" MaxHeight ="200" MaxWidth ="200" Source="{Binding ProfileImagePath}"
                                                   HorizontalAlignment="Center" >
                                    <Image.OpacityMask>
                                        <VisualBrush Visual="{Binding ElementName=ItemBorder}"/>
                                    </Image.OpacityMask>
                                </Image>
                            </Grid>
                            <Viewbox MaxWidth ="190" Margin="5,0,5,0" MaxHeight="15">
                                <TextBlock Name="Person" Text="{Binding ProfileName}" Tag="{Binding UserID}" HorizontalAlignment="Center" />
                            </Viewbox>
                        </StackPanel>
                        <!--</Viewbox>-->
                    </Border>
                </DataTemplate>
                        </ListBox.ItemTemplate>

                    </ListBox>

    </ScrollViewer>

集合存储在全局变量中,并使用 SQlCe 命令填充。

Public Shared CurrentPeopleList As New CollectionViewSource
Public Shared Current_People_List As New ObservableCollection(Of Currents)()

Public Shared Property CurrentList() As ObservableCollection(Of Currents)
    Get
        Return Current_People_List
    End Get
    Set(ByVal value As ObservableCollection(Of Currents))
        Current_People_List = value

    End Set
End Property

电流的自定义类别:

Public Class Currents
Implements INotifyPropertyChanged

Private ProfileNameValue As String

Private UserIDValue As Integer

Private ProfileImagePathValue As String

Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

#Region "Properties Getters and Setters" Public Property ProfileName() As String Get Return Me.ProfileNameValue End Get Set(ByVal value As String) Me.ProfileNameValue = value OnPropertyChanged("ProfileName") End Set End Property

Public Property UserID() As Integer
    Get
        Return Me.UserIDValue
    End Get
    Set(ByVal value As Integer)
        If value < 0 Then
            Throw New ArgumentException("User ID must be greater than 0 ")
        End If
        Me.UserIDValue = value
        OnPropertyChanged("UserID")
    End Set
End Property

Public Property ProfileImagePath() As String
    Get
        Return Me.ProfileImagePathValue
    End Get
    Set(ByVal value As String)
        Me.ProfileImagePathValue = RelativeProgramPath() & "Media\Pictures\" & value
        OnPropertyChanged("ProfileImagePath")
    End Set
End Property


#End Region

Public Sub New(ByVal UserID As Integer, ByVal ProfileName As String, ByVal ProfileImagePath As String)
    Me.ProfileNameValue = ProfileName
    Me.UserIDValue = UserID
    Me.ProfileImagePathValue = If(ProfileImagePath Like "pack://*", ProfileImagePath, RelativeProgramPath() & "Media\Pictures\" & ProfileImagePath)

End Sub

Protected Sub OnPropertyChanged(ByVal name As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
End Sub

End Class

最后,填充这些的方式是使用一个通用函数

 Private Sub Reload(ByVal CurrentID As Integer)
        Try


        Try
            ParentList = Nothing
            CurrentList = Nothing
            ChildrenList = Nothing
        Catch
        End Try
        Try
            Me.ParentListbox.ItemsSource = Nothing
            Me.CurrentListbox.ItemsSource = Nothing
            Me.ChildListbox.ItemsSource = Nothing
        Catch
        End Try
        Try

            CurrentPersonID = CurrentID
            'Load the Images Based on the people.
            Dim Ch = Load_Children_People(CurrentID)
            Dim C = Load_Current_People(CurrentID)
            Dim P = Load_Parent_People(CurrentID)

            ParentList = If(P.Count > 0, P, Nothing)
            CurrentList = If(C.Count > 0, C, Nothing)
            ChildrenList = If(Ch.Count > 0, Ch, Nothing)
        Catch
        End Try
        Try

            If ParentList IsNot Nothing Then _
                Me.ParentListbox.ItemsSource = CollectionViewSource.GetDefaultView(ParentList)

            If CurrentList IsNot Nothing Then _
                Me.CurrentListbox.ItemsSource = CollectionViewSource.GetDefaultView(CurrentList)
            If ChildrenList IsNot Nothing Then _
                Me.ChildListbox.ItemsSource = CollectionViewSource.GetDefaultView(ChildrenList)
        Catch
        End Try



    Catch
    End Try
    'For some reason this will not work without a pause. Not sure why.
    'FIXME Remove Pause Delay When able. 
    'Thread.Sleep(200)
End Sub

我使用了很多 try-catch 来尝试捕获错误,但到目前为止都没有成功。我怀疑错误发生在我似乎无法确定的 UI 线程期间。正如我之前提到的。任何帮助都会很棒。

4

0 回答 0