Treeview - Иерархический шаблон данных - Привязка не обновляется при изменении источника? - PullRequest
1 голос
/ 18 сентября 2009

Привет!

Я столкнулся с этой проблемой в своем проекте (Silverlight 3 с C #):

У меня есть TreeView, который привязан к дереву. Этот TreeView имеет HierarchicalDataTamplate в словаре ресурсов, который определяет различные элементы управления. Теперь я хочу спрятать (Visibility.Collapse) некоторые элементы в зависимости от того, есть у узла дочерние элементы или нет. Другие предметы должны быть видны при тех же условиях.

Это работает как очарование, когда я впервые связываю исходное дерево с TreeView, но когда я изменяю исходное дерево, видимость в дереве не меняется.

XAML - страница:

<controls:TreeView x:Name="SankeyTreeView" 
  ItemContainerStyle="{StaticResource expandedTreeViewItemStyle}"
  ItemTemplate="{StaticResource SankeyTreeTemplate}">
    <controls:TreeViewItem IsExpanded="True">
        <controls:TreeViewItem.HeaderTemplate>
            <DataTemplate>
                <TextBlock Text="This is just for loading and will be replaced directly after the data becomes available..."/>
            </DataTemplate>
        </controls:TreeViewItem.HeaderTemplate>
    </controls:TreeViewItem>
</controls:TreeView>

XAML - ResourceDictionary

<!-- Each node in the tree is structurally identical, hence only one Hierarchical
     Data Template that'll use itself on the children. -->
<Data:HierarchicalDataTemplate x:Key="SankeyTreeTemplate" 
  ItemsSource="{Binding Children}">
    <Grid Height="24">
    <TextBlock x:Name="TextBlockName" Text="{Binding Path=Value.name, Mode=TwoWay}" 
      VerticalAlignment="Center" Foreground="Black"/>
    <TextBox x:Name="TextBoxFlow" Text="{Binding Path=Value.flow, Mode=TwoWay}"
      Grid.Column="1" Visibility="{Binding Children, 
        Converter={StaticResource BoxConverter}, 
        ConverterParameter=\{box\}}"/>
    <TextBlock x:Name="TextBlockThroughput" Text="{Binding Path=Value.throughput, Mode=TwoWay}" 
      Grid.Column="1" Visibility="{Binding Children, 
        Converter={StaticResource BoxConverter}, ConverterParameter=\{block\}}"/>
    <Button x:Name="ButtonAddNode"/>
    <Button x:Name="ButtonDeleteNode"/>
    <Button x:Name="ButtonEditNode"/>
    </Grid>
</Data:HierarchicalDataTemplate>

Теперь, как вы можете видеть, TextBoxFlow и TextBlockThroughput совместно используют одно пространство. К чему я стремлюсь: значение «пропускной способности» узла - это то, сколько чего-то «течет» через этот узел от его дочерних элементов. Его нельзя изменить напрямую, поэтому я хочу отобразить текстовый блок. Только конечные узлы имеют TextBox, чтобы позволить кому-либо войти в «поток», который генерируется в этом конечном узле. (I.E .: Node.Throughput = Node.Flow + Sum (Children.Throughput), где Node.Flow = 0 для каждого не-листа.)

Что делает BoxConverter (глупое имя -.-):

public object Convert(object value, Type targetType, object parameter,
  System.Globalization.CultureInfo culture)
{
    if ((value as NodeList<TreeItem>).Count > 1) // Node has Children?
    {
        if ((parameter as String) == "{box}")
        {
            return Visibility.Collapsed;
        }
        else ((parameter as String) == "{block}")
        {
            return Visibility.Visible;
        }
    }
    else
    {
        /*
         * As above, just with Collapsed and Visible switched
         */
    }
}

Структура дерева, которое привязано к TreeView, по существу украдена из Dan Vanderboom (слишком много, чтобы вывести здесь весь код), за исключением того, что я здесь, конечно, использую ObservableCollection для дочерние элементы и элементы значения реализуют INotifyPropertyChanged.

Буду очень признателен, если кто-нибудь объяснит мне, почему вставка элементов в базовое дерево не обновляет видимость для блока и блока.

Заранее спасибо!

1 Ответ

0 голосов
/ 18 сентября 2009

Что происходит, так это то, что Converter вызывается всякий раз, когда свойство изменяется.

Однако добавление элементов в коллекцию не означает изменение свойства. В конце концов, это все та же коллекция. Что нужно сделать, чтобы ViewModel NotifyPropertyChanged при изменении коллекции Это заставит конвертер пересмотреть коллекцию.

...