Comment obtenir automatiquement mis à jour WPF TreeViewItems avec des valeurs basées sur les propriétés de la classe .Net?
-
13-10-2019 - |
Question
Bonjour. J'ai une classe avec des données provenant de InotifyPropertyChange. Les données proviennent d'un fil d'arrière-plan, qui recherche les fichiers avec certaine extension dans certains endroits. Propriété publique de réagit de manière classe à un onPropertyChange d'événement en mettant à jour les données dans un thread séparé. En outre, il est décrit en XAML TreeView, sur la base HierarhicalDataTemplates. Chaque TextBlock à l'intérieur des modèles fournis ItemsSource = "{Binding FoundFilePaths, mode = OneWay, NotifyOnTargetUpdated = true}".
<TreeView x:Name="FoundFiles_TreeView" Opacity="15" Background="White" BorderThickness="5" FontFamily="Arial" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Top" Height="360" FontWeight="Bold" Foreground="#FF539DBE" TargetUpdated="FoundFiles_TreeView_TargetUpdated">
<TreeView.ItemContainerStyle >
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="TreeViewItem.Tag" Value="InfoNode" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="Foreground" Value="Brown"/>
<Style.Triggers>
<Trigger Property="IsMouseCaptured" Value="True">
<Setter Property="IsSelected" Value="True"/>
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType = "{x:Type lightvedo:FilesInfoStore}" ItemsSource="{Binding FoundFilePaths, Mode=OneWay, NotifyOnTargetUpdated=True}">
<!--Здесь указываются узлы дерева-->
<StackPanel x:Name ="TreeNodeStackPanel" Orientation="Horizontal">
<TextBlock Margin="5,5,5,5" TargetUpdated="TextBlockExtensions_TargetUpdated">
<TextBlock.Text>
<MultiBinding StringFormat="Files with Extension {0}">
<Binding Path="FileExtension"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<Button x:Name="OpenFolderForThisFiles" Click="OnOpenFolderForThisFiles_Click" Margin="5, 3, 5, 3" Width="22" Background="Transparent" BorderBrush="Transparent" BorderThickness="0.5">
<Image Source="images\Folder.png" Height="16" Width="20" >
</Image>
</Button>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type lightvedo:FilePathsStore}">
<TextBlock Text="{Binding FilePaths, Mode=OneWay, NotifyOnTargetUpdated=True}" TargetUpdated="OnTreeViewNodeChildren_Update" />
</HierarchicalDataTemplate>
</TreeView.Resources>
<TreeView.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleX="-0.083"/>
<RotateTransform/>
<TranslateTransform X="-0.249"/>
</TransformGroup>
</TreeView.RenderTransform>
<TreeView.BorderBrush>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FF74591F" Offset="0" />
<GradientStop Color="#FF9F7721" Offset="1" />
<GradientStop Color="#FFD9B972" Offset="0.49" />
</LinearGradientBrush>
</TreeView.BorderBrush>
</TreeView>
Q: Pourquoi les données d'une classe dérivée de INotifyPropertyChange ne modifie pas l'affichage des éléments d'arbres. Est-ce que je comprends: L'interface fera INotifyPropertyChange automatiquement TreeViewItems réaffiché ou dois-je effectuer manuellement cette opération? Actuellement TreeViewItems pas mis à jour et PropertyChamged toujours nulle. Un sentiment qu'aucun abonné à l'événement OnPropertyChanged.
La solution
Vous n'avez pas besoin de régler la NotifyOnTargetUpdated
.
Au lieu de cela, assurez-vous de relever le PropertyChanged
événement (avec le approprié nom_propriété passé avec le PropertyChangedEventArgs
transmis au gestionnaire) sur l'entité mère à chaque fois que la collection de chemins est mis à jour, ou ont la propriété de navigation est une implémentation de INotifyCollectionChanged
.
Autres conseils
Je pense avoir trouvé la raison. Mon fil d'arrière-plan qui scanne en permanence le dossier crée une nouvelle instance de la classe de données provenant de INotifyPropertyChanged, qui sert de source pour TreeViewItems (ItemsSource). Ce principe est choisi parce qu'il est impossible de prédire ce qui devrait être fait avec une collection de fichiers trouvés: ajouter un nouvel élément, supprimer un existant ou modifier un existant. Si jamais je comptais substituer tour ItemsSource avec PropertyChange ne fonctionne pas. Donc, pour moi, la seule solution était d'appeler à partir du séparé (arrière-plan, la numérisation des dossiers) fil méthode Refresh () pour TreeViewItems.
public delegate void RefreshTreeViewItemsDelegate();
Dispatcher.FromThread(_guiThread).BeginInvoke(DispatcherPriority.Render, new RefreshTreeViewItemsDelegate (RefreshTreeItems))
// Some code ommited
private void RefreshTreeItems()
{
_popupWindow.FoundFiles_TreeView.ItemsSource = _treeViewNodesItems;
_popupWindow.FoundFiles_TreeView.Items.Refresh();
}
L'utilisation de cette situation avec ces classes héritées de INotifyPropertyChanged inutiles. ItemsControl, vous lient à cette classe attend seulement ajouter, supprimer ou modifier les articles, mais pas remplacer ItemsSource une nouvelle instance de la classe de données.