2011-04-23 56 views
2

你好,我有一個TreeView以下設置:刷新TreeView的CollectionViewSource的ObservableCollection項目已更改

<local:BuddyManager x:Key="bmBuddyManager" /> 

<CollectionViewSource x:Key="cvsBuddyManager" 
         Source="{Binding Source={StaticResource bmBuddyManager}, Path=Buddies}"> 
    <CollectionViewSource.GroupDescriptions> 
     <PropertyGroupDescription PropertyName="State" /> 
    </CollectionViewSource.GroupDescriptions> 
</CollectionViewSource> 

<DataTemplate x:Key="dtBuddyTemplate" DataType="{x:Type local:Buddy}"> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Text="{Binding Nick}" FontSize="12" FontWeight="Bold" /> 
     <TextBlock Text="{Binding GameHost}" FontSize="12" FontWeight="Bold" 
        Foreground="Purple" Margin="10,0,0,0" /> 
    </StackPanel> 
</DataTemplate> 

<HierarchicalDataTemplate x:Key="hdtBuddyCategoryTemplate" ItemsSource="{Binding Path=Items}" 
          ItemTemplate="{StaticResource dtBuddyTemplate}"> 
    <TextBlock Text="{Binding Path=Name}" FontWeight="Bold" Foreground="Gold" FontSize="15" /> 
</HierarchicalDataTemplate> 

     <TreeView ItemsSource="{Binding Source={StaticResource cvsBuddyManager}, Path=Groups}" 
        ItemTemplate="{StaticResource hdtBuddyCategoryTemplate}" 
        ContextMenuOpening="tvBuddies_ContextMenuOpening" 
        ContextMenuClosing="tvBuddies_ContextMenuClosing" 
        Background="Transparent" Margin="2,0,3,3"> 
     </TreeView> 

代碼背後:

<System.Runtime.InteropServices.ComVisible(False)> Public Enum BuddyState 
    Online 
    Offline 
    Blocked 
End Enum 

<System.Runtime.InteropServices.ComVisible(False)> Public Class Buddy 
    Implements INotifyPropertyChanged 

    Private _Nick As String 
    Private _IsInGame As Boolean 
    Private _GameHost As String 
    Private _State As BuddyState 

    Sub New(ByVal xwisNick As String) 
     _Nick = xwisNick 
     _State = BuddyState.Offline 
    End Sub 

    Sub New(ByVal xwisNick As String, ByVal state As BuddyState) 
     _Nick = xwisNick 
     _State = state 
    End Sub 

    Public Property Nick() As String 
     Get 
      Return _Nick 
     End Get 
     Set(ByVal value As String) 
      _Nick = value 
     End Set 
    End Property 

    Public Property IsInGame() As Boolean 
     Get 
      Return _IsInGame 
     End Get 
     Set(ByVal value As Boolean) 
      _IsInGame = value 

      If _IsInGame = False Then 
       GameHost = Nothing 
      End If 

      OnPropertyChanged("IsInGame") 
     End Set 
    End Property 

    Public Property GameHost() As String 
     Get 
      Return _GameHost 
     End Get 
     Set(ByVal value As String) 
      _GameHost = value 
      OnPropertyChanged("GameHost") 
     End Set 
    End Property 

    Public Property State() As BuddyState 
     Get 
      Return _State 
     End Get 
     Set(ByVal value As BuddyState) 
      _State = value 

      If value = BuddyState.Online Then 
       If _IsInGame Then 
        _IsInGame = False 
        _GameHost = Nothing 
       End If 
      End If 

      OnPropertyChanged("State") 
     End Set 
    End Property 

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged 

    ' Create the OnPropertyChanged method to raise the event 
    Protected Sub OnPropertyChanged(ByVal name As String) 
     Try 
      RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name)) 
     Catch 
     End Try 
    End Sub 
End Class 

Public Class BuddyManager 
    Implements INotifyPropertyChanged 

    Private ocBuddies As ObservableCollection(Of Buddy) = New ObservableCollection(Of Buddy) 

    Public ReadOnly Property Buddies As ObservableCollection(Of Buddy) 
     Get 
      Return ocBuddies 
     End Get 
    End Property 

    Public BuddyCheck As List(Of Buddy) = New List(Of Buddy) 
    Public IsCheckingForBuddies As Boolean = False 


    Public Function IsBuddy(ByVal XwisNick As String) As Boolean 
     Dim nick As String = XwisNick.ToLower 

     For Each b As Buddy In ocBuddies 
      If b.Nick = nick Then 
       Return True 
      End If 
     Next 

     Return False 
    End Function 

    Public Function IsInGame(ByVal XwisNick As String) As String 
     Dim nick As String = XwisNick.ToLower 

     For Each b As Buddy In ocBuddies 
      If b.Nick = nick Then 
       If b.IsInGame Then 
        Return b.GameHost 
       Else 
        Return Nothing 
       End If 
      End If 
     Next 

     Return Nothing 
    End Function 


    Public Function AddBuddy(ByVal XwisNick As String) As Boolean 
     Dim nick As String = XwisNick.ToLower 

     For Each b As Buddy In ocBuddies 
      If b.Nick = nick Then 
       Return False 
      End If 
     Next 

     ocBuddies.Add(New Buddy(nick)) 

     OnPropertyChanged("Buddies") 

     Return True 
    End Function 

    Public Function RemoveBuddy(ByVal XwisNick As String) As Boolean 
     Dim nick As String = XwisNick.ToLower 

     For i As Integer = 0 To ocBuddies.Count - 1 
      If ocBuddies(i).Nick = nick Then 
       ocBuddies.RemoveAt(i) 

       OnPropertyChanged("Buddies") 

       Return True 
      End If 
     Next 

     Return False 
    End Function 

    Public Function BlockBuddy(ByVal XwisNick As String) As Boolean 
     Dim nick As String = XwisNick.ToLower 

     For i As Integer = 0 To ocBuddies.Count - 1 
      If ocBuddies(i).Nick = nick Then 
       ocBuddies(i).State = BuddyState.Blocked 

       OnPropertyChanged("Buddies") 

       Return True 
      End If 
     Next 

     ocBuddies.Add(New Buddy(nick, BuddyState.Blocked)) 

     OnPropertyChanged("Buddies") 

     Return True 
    End Function 

    Public Function UnblockBuddy(ByVal XwisNick As String) As Boolean 
     Dim nick As String = XwisNick.ToLower 

     For i As Integer = 0 To ocBuddies.Count - 1 
      If ocBuddies(i).Nick = nick Then 
       ocBuddies(i).State = BuddyState.Offline 

       OnPropertyChanged("Buddies") 

       Return True 
      End If 
     Next 

     Return False 
    End Function 


    Public Sub UpdateOnlineStatus(ByVal XwisNick As String, ByVal online As Boolean) 
     Dim nick As String = XwisNick.ToLower 

     For i As Integer = 0 To ocBuddies.Count - 1 
      If ocBuddies(i).Nick = nick Then 
       If online Then 
        ocBuddies(i).State = BuddyState.Online 
       Else 
        ocBuddies(i).State = BuddyState.Offline 
       End If 
       OnPropertyChanged("Buddies") 

       Exit For 
      End If 
     Next 

     RaiseEvent BuddyOnlineStatusChanged(nick, online) 
    End Sub 

    Public Sub UpdateInGameStatus(ByVal XwisNick As String, ByVal gamehost As String) 
     Dim nick As String = XwisNick.ToLower 

     For i As Integer = 0 To ocBuddies.Count - 1 
      If ocBuddies(i).Nick = nick Then 
       ocBuddies(i).IsInGame = True 
       ocBuddies(i).GameHost = gamehost 

       OnPropertyChanged("Buddies") 

       RaiseEvent BuddyGameStatusChanged(nick, gamehost) 

       Exit For 
      End If 
     Next 
    End Sub 


    Public Sub FillBuddyCheck() 
     BuddyCheck = ocBuddies.Where(Function(bud) bud.State <> BuddyState.Blocked).ToList 
    End Sub 

    Public Function GetBuddies() As IEnumerable(Of Buddy) 
     Return ocBuddies.Where(Function(bud) bud.State <> BuddyState.Blocked) 
    End Function 

    Public Sub Sort() 
     ocBuddies.OrderBy(Function(bud) bud.Nick) 
     OnPropertyChanged("Buddies") 
    End Sub 

    Public Function Count() As Integer 
     Return GetBuddies.Count 
    End Function 


    Public Event BuddyOnlineStatusChanged(ByVal nick As String, ByVal online As Boolean) 
    Public Event BuddyGameStatusChanged(ByVal nick As String, ByVal gamehost As String) 


    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged 

    ' Create the OnPropertyChanged method to raise the event 
    Protected Sub OnPropertyChanged(ByVal name As String) 
     Try 
      RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name)) 
     Catch 

     End Try 
    End Sub 
End Class 

如何與類交互:

Public Function GetBuddyManager() As BuddyManager 
     Try 
      Return DirectCast(FindResource("bmBuddyManager"), BuddyManager) 
     Catch ex As Exception 
      MessageBox.Show("Error getting buddy manager object: " & ex.ToString()) 
      Application.Current.Shutdown() 

      Return Nothing 
     End Try 
    End Function 

GetBuddyManager().UpdateOnlineStatus(GetBuddyManager().BuddyCheck(0).Nick, True) 

綁定和分組運行良好,唯一的問題是當我設置一個特定的「夥伴」在線或阻止子節點不移動或改變。

我試圖讓這個工作像MSN樹視圖在哪裏人們下線和在線。

任何幫助表示讚賞,我一直在研究這個問題一個月左右的研究和重大研究,沒有運氣。

謝謝你的時間。

+1

3個問題:1:是否有一個原因,你使用的是TreeView而不是ListBox.GroupStyle的ListBox?第二:你是否曾嘗試將collectionchanged事件處理程序添加到CollectionViewSource.View或CollectionViewSource.View.Groups [0]以查看它們是否實際上正在更改?第3:UI是否更新並顯式調用CollectionViewSource.View.Refresh? – 2011-04-27 19:08:21

+0

第三:是的,我的標籤更新(因爲我有作爲每個項目的堆疊面板中的第二個標籤的狀態)。第二:CollectionViewSource.View沒有任何我能看到的事件。第一:我會嘗試。 謝謝! – tcables 2011-04-27 19:11:27

回答

0

看起來您需要VisualColor的State屬性中的OnPropertyChanged事件。用戶界面沒有收到應該更新視覺顏色的通知。它知道國家的價值已經發生了變化,但所有這一切意味着國家財產的更新必然會發生。

建議將這些顏色放在XAML中,並在您的物品上寫入一個DataTrigger,以評估狀態並更改顏色以適合該顏色。

接下來,當您設置狀態時,您是否在運行時查看了CollectionViewSource,看看它是如何排序的?你是否在CVS視圖上調用刷新?

+0

我從這個例子中刪除了這個。由於這完全不是我的問題或問題所在,但至少感謝你看我的問題。 – tcables 2011-04-28 03:49:31

+0

當你改變屬性的時候,你會問爲什麼你的物品在樹形視圖中沒有改變位置?如果更改State屬性,執行OnPropertyChanged並刷新CollectionView,會發生什麼情況?沒有?就我個人而言,我還沒有嘗試過這樣的實施。在深入研究treeviews和CollectionViewSource之前,我選擇了MVVM。然而,我已經得到了這個與視圖模型一起工作,並沒有很多。在那種情況下,我有幾個可觀察的集合在某些「國家」中持有對象,我會來回移動物品。像魅力一樣工作。 – CodeWarrior 2011-04-28 04:10:50

+0

「更改狀態屬性,執行OnPropertyChanged並刷新CollectionView」前幾天我嘗試過,它確實有效 - 但會導致樹閃爍,關閉並鬆動所選項目。在使用上下文菜單或點擊刪除等選定項目時,會變得非常煩人。 – tcables 2011-04-28 16:04:34

相關問題