Как автоматически обновлять WPF TreeViewItems со значениями, основанными на свойствах класса .Net? - PullRequest
1 голос
/ 26 декабря 2010

Доброе утро. У меня есть класс с данными, полученными из InotifyPropertyChange. Данные поступают из фонового потока, который ищет файлы с определенным расширением в определенных местах. Открытое свойство класса реагирует на событие OnPropertyChange, обновляя данные в отдельном потоке. Кроме того, они описаны в XAML TreeView на основе HierarhicalDataTemplates. Каждый текстовый блок внутри шаблонов предоставлен 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>

В: Почему данные из класса, производного от INotifyPropertyChange, не влияют на отображение элементов дерева. Я понимаю: интерфейс заставит INotifyPropertyChange автоматически перерисовывать TreeViewItems или мне нужно вручную выполнить эту операцию? В настоящее время TreeViewItems не обновляется, а PropertyChamged всегда имеет значение null. Такое ощущение, что нет подписчиков на событие OnPropertyChanged.

Ответы [ 2 ]

0 голосов
/ 26 декабря 2010

Я думаю, что нашел причину.Мой фоновый поток, который постоянно сканирует папку, создает новый экземпляр класса данных, производный от INotifyPropertyChanged, который служит источником для TreeViewItems (ItemsSource).Этот принцип выбран потому, что невозможно предсказать, что следует делать с набором найденных файлов: добавить новый элемент, удалить существующий или отредактировать существующий.Если я когда-либо намеревался заменить трюк ItemsSource на PropertyChange, то он не работает.Поэтому для меня единственным решением было вызвать из отдельного (фонового, сканирующего папки) потока метод Refresh () для 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();
}

Использование этой ситуации с этими классами, унаследованными от INotifyPropertyChanged, бесполезно.ItemsControl, привязка к этому классу предполагает только добавление, удаление или изменение элементов, но не замену ItemsSource новым экземпляром класса данных.

0 голосов
/ 26 декабря 2010

Вам не нужно устанавливать NotifyOnTargetUpdated.

Вместо этого обязательно вызывайте событие PropertyChanged (с соответствующим именем свойства, передаваемым с PropertyChangedEventArgs, передаваемым в обработчик) каждый раз в родительском объекте коллекция путей обновлена ​​или имеет свойство навигации быть реализацией INotifyCollectionChanged.

...