Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
 Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
Как сделать выделение одного узла в TreeView в Silverligth, если при отображении я использую шаблон:

 <sdk:TreeView x:Name="treeView1" Background="White" SelectedItemChanged="treeView1_SelectedItemChanged" Margin="0,1,1,1" Height="514" Width="301">
                <sdk:TreeView.ItemTemplate>
                    <sdk:HierarchicalDataTemplate ItemsSource="{Binding SubNodes}">
                    	<StackPanel>
                    		<TextBlock Text="{Binding FullHeader}" Tag="{Binding Tag}" />
                    	</StackPanel>
                    </sdk:HierarchicalDataTemplate>
                </sdk:TreeView.ItemTemplate>
 </sdk:TreeView>


А для пунктов меню я использую список экземпляров моего типа.

/// присвоение коллекции
List<TestServiceClient.ClassNode> itemsTrvNodes = new List<TestServiceClient.ClassNode>();
itemsTrvNodes.Add(cln);
this.treeView1.ItemsSource = itemsTrvNodes;



public ClassNode()
//описание класса
	{
		//
		// TODO: добавьте логику конструктора
		//
        SubNodes = new List<ClassNode>();
        
    }   

    public int _IntTypeNode = new int();
 

    public int _IdNode = new int();

 public List<ClassNode> SubNodes { get; set; }
}


Как сделать выделение одного определенного узла дерева, причем он будет зависит от разных факторов.
28 дек 12, 14:47    [13700859]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
Можно ли как то выделить узел в дереве?
14 янв 13, 16:18    [13767846]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
unknownfromrus
Member

Откуда:
Сообщений: 345
Solomka,

Поищи мой пост по TreeView. Я по нему очень много чего расписывал - а именно, изменение ControlTemplate. Дело в том что там будут подводные камни если оставить все как есть по умолчанию.
Я дмаю тебе не составит труда сделать небольшие изменения для добавления дополнительных тригеров для выделения.
А именно - добавь свое свойство булевского значения. Сажай в него логику выделения и добавляй его в MultiTriggers (Data). По идее ничего сложного нет
15 янв 13, 21:12    [13774847]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
unknownfromrus
Solomka,

Поищи мой пост по TreeView. Я по нему очень много чего расписывал - а именно, изменение ControlTemplate. Дело в том что там будут подводные камни если оставить все как есть по умолчанию.
Я дмаю тебе не составит труда сделать небольшие изменения для добавления дополнительных тригеров для выделения.
А именно - добавь свое свойство булевского значения. Сажай в него логику выделения и добавляй его в MultiTriggers (Data). По идее ничего сложного нет


Нашла твой пост [url=]https://www.sql.ru/forum/actualthread.aspx?bid=35&tid=982313&hl=[/url]
Только особо не поняла, как он может мне помочь.

Нашла в интернете пример Как выделить первый узел дерева:
        private void SelectFistItemInCatTreeView()
        {
            TreeViewItem item =
                treeView1.ItemContainerGenerator.ContainerFromItem(treeView1.Items[0]) as TreeViewItem;
            if (item != null)
            {
                item.IsSelected = true;
            }
            
        }

Этот код работает. Достаточно вызвать этот метод и сам узел выделится.

Пыталась дальше отталкиваться...
В каком нибудь методе определяем параметр по которому нам надо выделить узел:
private void button1_Click(object sender, RoutedEventArgs e)
        {
              string temp = "1-171";            
              SetSelectNodeTag(temp);
        }

По идее метод SetSelectNodeTag для выделение одного узла.

  private void SetSelectNodeTag(string varString)
        {
             for (int i = 0; i < treeView1.Items.Count; i++)
            {
                TreeViewItem item =
                    treeView1.ItemContainerGenerator.ContainerFromItem(treeView1.Items[i]) as TreeViewItem;
                 
                SelectNodeTag03(varString, item);
            }
        }


Метод SelectNodeTag по идее должен пробегать рекурсивно по всем узлам дерева, и если обнаружит искомый узел, то выделить его
private void SelectNodeTag03(string varString, TreeViewItem triCur)
        {
             
            ClassNode nd = (ClassNode)triCur.Header; // здесь возникает ошибка при первом рекурсивном заходе
            if (nd.Tag.ToString() == varString)
            {
                 
                triCur.IsSelected = true;
            }
            else
            {
                for (int index = 0; index < triCur.Items.Count; index++)
                {
 
                    TreeViewItem searchItem = triCur.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem;
                     
                    TreeViewItem itemTreeViewItem = triCur.ItemContainerGenerator.ContainerFromItem(searchItem) as TreeViewItem;
                    TreeViewItem itemTreeViewItem2 = triCur.ItemContainerGenerator.ContainerFromItem(triCur.Items[index]) as TreeViewItem;
                    TreeViewItem itemTreeViewItem3 = treeView1.ItemContainerGenerator.ContainerFromItem(triCur.Items[index]) as TreeViewItem;
                   // Все три переменные null
                    SelectNodeTag03(varString, itemTreeViewItem);
                }
            }

        }

Однако если пользоваться ранее успешно примененной логикой, не удается "достать" хотя бы один подузел.
При первом же проходе в цикле for переменные "searchItem", "itemTreeViewItem", "itemTreeViewItem2", "itemTreeViewItem3" - имею пустые значения и в следующем первом рекурсивном заходе в метод возникает ошибка в строчке:
ClassNode nd = (ClassNode)triCur.Header

Что нельзя обращаться к NULL.

Причем если определить первый узел дерева превого уровня, например указав string temp = "1-169"; (169 - родительский для 171), то всё нормльно работает, потому что не пытается достать подузел.
16 янв 13, 13:50    [13778005]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
unknownfromrus
Member

Откуда:
Сообщений: 345
Solomka,

Так давай по порядку.
Я правильно понимаю, что ты хочешь чтобы выделение узла в TreeView происходило не только по стандартным условиям, но ты еще свои добавишь (логику по которой должно происходить выделение)?
Мой пост тебе в помощь в том случае если ты захочешь переопределить Template у TreeView - так как возникнут подводные камни, о которых я там описывал.
В твоем же случае - чтобы добавить логику выделения - надо создать свойство, значение которого (Bool типа) будет определяться твоей логикой. И это свойство подцепить в условие IsSelected (найти его можно в Template - где определяется каким цветом и т.д. будет определяться выбранный узел). Так называемый MultiTrigger
16 янв 13, 18:02    [13780317]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
unknownfromrus
Solomka,

Так давай по порядку.
Я правильно понимаю, что ты хочешь чтобы выделение узла в TreeView происходило не только по стандартным условиям, но ты еще свои добавишь (логику по которой должно происходить выделение)?

Что именно подразумевается под стандартными условиями? Если под стандартными условиями подразумевается что пользователь сам выделяет необходимый узел, то ДА, мне нужно добавить свою логику, когда будет выделятся узел.

unknownfromrus
В твоем же случае - чтобы добавить логику выделения - надо создать свойство, значение которого (Bool типа) будет определяться твоей логикой. И это свойство подцепить в условие IsSelected (найти его можно в Template - где определяется каким цветом и т.д. будет определяться выбранный узел). Так называемый MultiTrigger

Я в Silverligth новичек, вот эта часть текста мне не очень понятна.

Если я правильно понимаю, то Template я так переопределяю...
                <sdk:TreeView.ItemTemplate >
                    
                    <sdk:HierarchicalDataTemplate ItemsSource="{Binding SubNodes}">
                    	<StackPanel>
                    		<TextBlock Text="{Binding FullHeader}" Tag="{Binding Tag}" />
                    	</StackPanel>                        
                    </sdk:HierarchicalDataTemplate>
                    
                </sdk:TreeView.ItemTemplate>


Если пишу сюда:
            <sdk:TreeView x:Name="treeView1" Background="White" SelectedItemChanged="treeView1_SelectedItemChanged" Margin="0,1,1,1" Height="514" Width="301">
               
                <sdk:TreeView.ItemTemplate >
                    
                    <sdk:HierarchicalDataTemplate ItemsSource="{Binding SubNodes}">
                    	<StackPanel>
                    		<TextBlock Text="{Binding FullHeader}" Tag="{Binding Tag}" />
                    	</StackPanel>                        
                    </sdk:HierarchicalDataTemplate>
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                </sdk:TreeView.ItemTemplate>
            </sdk:TreeView>

То в дизайнере, выдается ошибка
Свойство "ItemTemplate" установлено больше одного раза.

Куда надо прописать свойство, чтобы можно было выделать не только узлы первого уровня, но и большего уровня вложенности?
17 янв 13, 10:21    [13782776]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
unknownfromrus
Member

Откуда:
Сообщений: 345
Solomka,

Расписывать че-то не хочется.
Давай сделаем так - дай мне свой примерчик что ты хочешь сделать - я его поправлю - добавив то что ты хочешь
17 янв 13, 16:18    [13786334]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
unknownfromrus
Solomka,

Расписывать че-то не хочется.
Давай сделаем так - дай мне свой примерчик что ты хочешь сделать - я его поправлю - добавив то что ты хочешь


Ссылка на архив: http://yadi.sk/d/drPA-r0D20ITx
Не совсем родной проект, я его упростила, чтобы не отвлекать на сторонние вещи.
Слева дерево. справа список с ID узлов дерева.
И по ID надо выбрать узел в дереве.
21 янв 13, 15:51    [13803932]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
enigmatic
Member

Откуда:
Сообщений: 729
автор
ClassNode nd = (ClassNode)triCur.Header
Что здесь происходит? Ты пытаешься взять Header из triCur, из типа TreeViewItem. Ты где-то до этого кладешь в Header ClassNode? Если ты этого не делаешь, то TreeViewItem'у в Header'е неоткуда взяться.

Насколько я вижу по коду, тебе нужно делать:
ClassNode nd = (ClassNode)triCur.DataContext
а не то, что ты сейчас делаешь.

Во-вторых, лучше не доставать из TreeView TreeViewItem'ы при помощи ItemContainerGenerator'а и не работать с элементами интерфейса (TreeViewItem'ами) вручную, а, как тебе уже верно посоветовали, завести в твоем классе данных (ClassNode) свойство IsSelected, реализовать в ClassNode интерфейс INotifyPropertyChanged и установить двухсторонний (TwoWay) биндинг между TreeViewItem'ами и ClassNode с помощью ItemContainerStyle или чего-то подобного. Далее ты можешь выбрать некоторое количество ClassNode'ов, выставить им IsSelected в true и связанные с ними TreeViewItem'ы сами станут выбранными.

В-третьих, попробуй скачать проект по своей ссылке. У меня ничего не получилось.
23 янв 13, 15:00    [13815772]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
enigmatic

В-третьих, попробуй скачать проект по своей ссылке. У меня ничего не получилось.


Странно, у меня всё получается.
На всякий случай ещё сюда выложила.
[url=http://rapidshare.com/files/1787905320/wsTestSelectNodeToInet.zip
]http://rapidshare.com/files/1787905320/wsTestSelectNodeToInet.zip
[/url]
24 янв 13, 09:05    [13819364]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
enigmatic
автор
ClassNode nd = (ClassNode)triCur.Header
Что здесь происходит? Ты пытаешься взять Header из triCur, из типа TreeViewItem. Ты где-то до этого кладешь в Header ClassNode? Если ты этого не делаешь, то TreeViewItem'у в Header'е неоткуда взяться.

Насколько я вижу по коду, тебе нужно делать:
ClassNode nd = (ClassNode)triCur.DataContext
а не то, что ты сейчас делаешь.

Я ничего не кладу в Header, я через отладку нашла, что это поле содержит информацию о экземпляре класса ClassNode.
ClassNode nd = (ClassNode)triCur.DataContext

Попробовала всё равно не помогает.
enigmatic

Во-вторых, лучше не доставать из TreeView TreeViewItem'ы при помощи ItemContainerGenerator'а и не работать с элементами интерфейса (TreeViewItem'ами) вручную, а, как тебе уже верно посоветовали, завести в твоем классе данных (ClassNode) свойство IsSelected, реализовать в ClassNode интерфейс INotifyPropertyChanged и установить двухсторонний (TwoWay) биндинг между TreeViewItem'ами и ClassNode с помощью ItemContainerStyle или чего-то подобного. Далее ты можешь выбрать некоторое количество ClassNode'ов, выставить им IsSelected в true и связанные с ними TreeViewItem'ы сами станут выбранными.

Не очень понимаю, может ли мне это помочь.
Мне же надо чтобы выделенные узлы дерева менялись, в процессе работы и не были одним и тем же постоянным узлом...
24 янв 13, 09:22    [13819442]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
enigmatic
автор
ClassNode nd = (ClassNode)triCur.Header
Что здесь происходит? Ты пытаешься взять Header из triCur, из типа TreeViewItem. Ты где-то до этого кладешь в Header ClassNode? Если ты этого не делаешь, то TreeViewItem'у в Header'е неоткуда взяться.

Насколько я вижу по коду, тебе нужно делать:
ClassNode nd = (ClassNode)triCur.DataContext
а не то, что ты сейчас делаешь.



Тут получается ошибка в строке
ClassNode nd = (ClassNode)triCur.Header

возникает из-за того что мы в метод передаем переменную itemTreeViewItem2 NULL.
 SelectNodeTag03(varString, itemTreeViewItem2);
24 янв 13, 10:54    [13820006]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
enigmatic
Member

Откуда:
Сообщений: 729
Solomka
Я ничего не кладу в Header, я через отладку нашла, что это поле содержит информацию о экземпляре класса ClassNode.
Странно, по идее в Header'e не должно быть ClassNode, но ClassNode должен быть в DataContext'е triCur.

Solomka
enigmatic

Во-вторых, лучше не доставать из TreeView TreeViewItem'ы при помощи ItemContainerGenerator'а и не работать с элементами интерфейса (TreeViewItem'ами) вручную, а, как тебе уже верно посоветовали, завести в твоем классе данных (ClassNode) свойство IsSelected, реализовать в ClassNode интерфейс INotifyPropertyChanged и установить двухсторонний (TwoWay) биндинг между TreeViewItem'ами и ClassNode с помощью ItemContainerStyle или чего-то подобного. Далее ты можешь выбрать некоторое количество ClassNode'ов, выставить им IsSelected в true и связанные с ними TreeViewItem'ы сами станут выбранными.
Не очень понимаю, может ли мне это помочь.
Мне же надо чтобы выделенные узлы дерева менялись, в процессе работы и не были одним и тем же постоянным узлом...
Эм, функционал редактирования узлов нужен?

Solomka
http://rapidshare.com/files/1787905320/wsTestSelectNodeToInet.zip
rapidshare
Скачивание невозможно
Download permission denied by uploader. (0b67c2f5)

Solomka
Ссылка на архив: http://yadi.sk/d/drPA-r0D20ITx
Тут выдается первая страница, где есть кнопка "просмотреть", по которой куча файлов, которые нельзя скачать.

автор
Тут получается ошибка в строке
ClassNode nd = (ClassNode)triCur.Header

возникает из-за того что мы в метод передаем переменную itemTreeViewItem2 NULL.
SelectNodeTag03(varString, itemTreeViewItem2);
Хорошо, если у тебя там в Header'e всё-таки лежит ClassNode, то лучше выложи свой проект где-нибудь откуда скачать можно.
24 янв 13, 12:18    [13820642]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
enigmatic
возникает из-за того что мы в метод передаем переменную itemTreeViewItem2 NULL.
SelectNodeTag03(varString, itemTreeViewItem2);
Хорошо, если у тебя там в Header'e всё-таки лежит ClassNode, то лучше выложи свой проект где-нибудь откуда скачать можно.


https://docs.google.com/file/d/0BxprtRW4TI9QWjRkWXBEcGxYOHM/edit

http://depositfiles.com/files/0dvgppejn

http://disk.yandex.ru/public/?hash=85sSp5Ko4N1JPPvUVo6pTeb4nWqfxhhYcWV4li0RjOo%3D
(тут есть кнопочка посмотреть и скачать и сохранить на яндекс.диск)
24 янв 13, 15:26    [13822189]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
enigmatic
Member

Откуда:
Сообщений: 729
Solomka,

Окей, TreeViewItem зачем-то хранит информацию о привязанных данных не в DataContext (где должен, по идее), а в Header (которого у него нет, по сути). Это во-первых.

Во-вторых, сложно сказать почему именно не работает то, что ты хочешь. Просто код кошмарен и его проще переписать заново.
В теме уже указывалось как это лучше сделать.
unknownfromrus
В твоем же случае - чтобы добавить логику выделения - надо создать свойство, значение которого (Bool типа) будет определяться твоей логикой. И это свойство подцепить в условие IsSelected (найти его можно в Template - где определяется каким цветом и т.д. будет определяться выбранный узел).
29 янв 13, 11:25    [13843213]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
enigmatic
Solomka,

Окей, TreeViewItem зачем-то хранит информацию о привязанных данных не в DataContext (где должен, по идее), а в Header (которого у него нет, по сути). Это во-первых.

При замене на DataContext все арвно происходит ошибка.
enigmatic
Во-вторых, сложно сказать почему именно не работает то, что ты хочешь. Просто код кошмарен и его проще переписать заново.
В теме уже указывалось как это лучше сделать.

Если бы , было мне бы понятно, то я бы уже не спрашивала.
Можно скинуть пример, чтобы попонятнее было?

Кошмарен - не кошмарен... мой код... сказать сложно.
В интернете нашла пример с таким кодом
И он почти рабочий, для узлом первого уровня
4 фев 13, 09:03    [13870402]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Solomka
Member

Откуда: Москва
Сообщений: 185
unknownfromrus
В твоем же случае - чтобы добавить логику выделения - надо создать свойство, значение которого (Bool типа) будет определяться твоей логикой. И это свойство подцепить в условие IsSelected (найти его можно в Template - где определяется каким цветом и т.д. будет определяться выбранный узел). Так называемый MultiTrigger

Можете скинуть пример кода?
А то не совсем понятно...
6 фев 13, 13:10    [13883786]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
unknownfromrus
Member

Откуда:
Сообщений: 345
Solomka,

Давай скидывай
7 фев 13, 11:19    [13889219]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6021
Сам недавно столкнулся с такой проблемой. Вроде бы выделить узел по его датаконтексту - не особенно трудный вопрос:
public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register(
      "SelectedObject", typeof(object), typeof(WxTreeView),
      new PropertyMetadata(SelectedObjectChangedCallback));

[Bindable(true)]
public object SelectedObject
{
  get { return GetValue(SelectedObjectProperty); }
  set { SetValue(SelectedObjectProperty, value); }
}

private static void SelectedObjectChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs)
{
  var treeView = (WxTreeView)obj;
  if (ReferenceEquals(eventArgs.OldValue, eventArgs.NewValue)) return;
  var item = GetSelectedItem(treeView, eventArgs.NewValue) as TreeViewItem;
  if (item == null) return;
  item.Focus();
}
private static ItemsControl GetSelectedItem(ItemsControl parent, object itemToSelect)
{
  if (parent == null) return null;
  var childTreeNode = parent.ItemContainerGenerator.ContainerFromItem(itemToSelect) as TreeViewItem;
  if (childTreeNode!=null)
    return childTreeNode;
  foreach (var childItem in parent.Items)
  {
    var childItemsControl = parent.ItemContainerGenerator.ContainerFromItem(childItem) as ItemsControl;
    var res = GetSelectedItem(childItemsControl, itemToSelect);
    if (res!=null) return res;
  }
  return null;
}

однако вся проблема - в виртуализации отрисовки: свернутые узлы не отображают своего содержимого, фактически - не содержат его, и на уровне вложенности глубже 2 от корня, если развернут только корень, ItemContainerGenerator.ContainerFromItem(itemToSelect) возвращает null. Т.е. по мере прохода по дереву вглубь надо разворачивать узлы. Но просто установки IsExpanded = true недостаточно - при этом только устанавливается значение DependencyProperty, а заполнение ItemsControl узлами порисходит в отложенном порядке. У TreeView есть метод ExpandSubtree(), но он разварачивает всё поддерево, а надо развернуть только 1 уровень. Пришлось взять рефлектор, влезть в код TreeViewItem, взять оттуда реализацию ExpandSubtree, и модифицировать её (часть используемых методов/свойств там protected internal, поэтому пришлось прибегнуть к reflection). Получилось вот так:
public static void TraverseDown(this ItemsControl root, IEnumerable<object> traverse)
{
  if (traverse == null || !traverse.Any())
    return;
  var ic = root;
  foreach(var o in traverse)
  {
    var tvi = ic.ItemContainerGenerator.ContainerFromItem(o) as TreeViewItem;
    if (tvi == null) break;
    tvi.UpdateLayout();
    if (!tvi.IsExpanded) ExpandLevel(tvi);
    ic = tvi;
  }
}

public static Panel ItemsHost(this TreeViewItem item)
{
  var ihp = typeof(TreeViewItem).GetProperty("ItemsHost", BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Instance);
  return ihp.GetValue(item, null) as Panel;
}

private static void ExpandLevel(TreeViewItem item)
{
  if (item == null) return;
  if (item.GetIsBound(TreeViewItem.IsExpandedProperty))
    item.SetBindingValue(TreeViewItem.IsExpandedProperty, true);
  else
    item.SetValue(TreeViewItem.IsExpandedProperty, true);
  item.ApplyTemplate();
  var itemsPresenter = (ItemsPresenter)item.Template.FindName("ItemsHost", item);
  if (itemsPresenter != null)
    itemsPresenter.ApplyTemplate();
  else
    item.UpdateLayout();
  var virtualizingPanel = item.ItemsHost() as VirtualizingPanel;
  var egInfo = typeof(Panel).GetMethod("EnsureGenerator", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance);
  egInfo.Invoke(item.ItemsHost(), null); //item.ItemsHost().EnsureGenerator();
  var biivInfo = typeof(VirtualizingPanel).GetMethod("BringIndexIntoView", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance);
  var i = 0;
  var count = item.Items.Count;
  while (i < count)
  {
    if (virtualizingPanel != null)
    {
      biivInfo.Invoke(virtualizingPanel, new object[] { i }); //virtualizingPanel.BringIndexIntoView(i);
    }
    else
    {
      var treeViewItem = (TreeViewItem)item.ItemContainerGenerator.ContainerFromIndex(i);
      treeViewItem.BringIntoView();
    }
    i++;
  }
}

В комментариях - то, что было в исходном коде. Методы GetIsBound/SetBindingValue используются для того, чтобы в случае, если свойство IsExpanded имеет привязку к модели, изменять (опять же через reflection) свойство модели, а не значение IsExpandedProperty непосредственно, т.к. это сбросит биндинг свойства.
Ну, и в результате получаем
private static void SelectedObjectChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs)
{
  var treeView = (WxTreeView)obj;
  if (ReferenceEquals(eventArgs.OldValue, eventArgs.NewValue)) return;
  var item = GetSelectedItem(treeView, eventArgs.NewValue) as TreeViewItem;
  if (item == null)
  {
    var traversable = eventArgs.NewValue as ITraversable;
    if (traversable == null) return;
    treeView.TraverseDown(traversable.Traverse);
    item = GetSelectedItem(treeView, eventArgs.NewValue) as TreeViewItem;
  }
  if (item == null) return;
  item.Focus();
}

Интрефейс ITraversable заставляет объект модели дерева возвращать все родительские узлы дерева от корня до требуемого элемента. Выглядит он так:
public interface ITraversable
{
  IEnumerable<object> Traverse { get; }
}

и реализуется рекурсией.
10 фев 13, 15:18    [13904350]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
enigmatic
Member

Откуда:
Сообщений: 729
Сон Веры Павловны,

Хм, а зачем решать проблему на уровне контролов (TreeViewItem'ов), если можно объявить свойство IsSelected (+INPC) в модели и забиндиться на него?
11 фев 13, 06:22    [13906472]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6021
enigmatic
Хм, а зачем решать проблему на уровне контролов (TreeViewItem'ов), если можно объявить свойство IsSelected (+INPC) в модели и забиндиться на него?

Затем, что я писал выше:
Сон Веры Павловны
Но просто установки IsExpanded = true недостаточно - при этом только устанавливается значение DependencyProperty, а заполнение ItemsControl узлами происходит в отложенном порядке.

Аналогично без толку выставлять в true свойство модели, забинденное на IsExpanded - ItemContainerGenerator.ContainerFromItem(itemToSelect) будет возвращать null, т.к. ItemsControl узла на момент после установки свойства не заполнится соответствующими контролами. Это всё проверено на практике.
11 фев 13, 09:45    [13906847]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
unknownfromrus
Member

Откуда:
Сообщений: 345
Сон Веры Павловны,

Не знаю почему бестолку.
Недавно сделал тривью в комбобоксе. У меня были вложенные объекты. К объектам добавил свойство IsExpanded (поле класса объекта). Установил биндинг - и у меня разворачивается независимо от вложенности объектов (ЗАполнение объектов реализовано через HierarchiDataTemplate). Аналогично с IsSelected.
Вытаскивать из проекта Тривью я не хочу, чтобы тут выкладывать.
Тот кто поднимал тему - ему по ходу по фиг - раз до сих пор не выложил примерчик кода - я хотел попробовать в нем переопределить тривью
11 фев 13, 12:53    [13907991]     Ответить | Цитировать Сообщить модератору
 Re: Как сделать выделение одного узла в TreeView в Silverligth?  [new]
Obrazer
Member

Откуда: Смоленск
Сообщений: 1419
unknownfromrus
Установил биндинг - и у меня разворачивается независимо от вложенности объектов (ЗАполнение объектов реализовано через HierarchiDataTemplate). Аналогично с IsSelected.


А где биндинг делается и какого контрола? В HierarchiDataTemplate что-то или в самом TreeView?
20 мар 13, 02:00    [14070257]     Ответить | Цитировать Сообщить модератору
Все форумы / WPF, Silverlight Ответить