Гость
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Как сделать выделение одного узла в TreeView в Silverligth? / 23 сообщений из 23, страница 1 из 1
28.12.2012, 14:47
    #38096228
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Как сделать выделение одного узла в TreeView в Silverligth, если при отображении я использую шаблон:

Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
 <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>



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

Код: c#
1.
2.
3.
4.
/// присвоение коллекции
List<TestServiceClient.ClassNode> itemsTrvNodes = new List<TestServiceClient.ClassNode>();
itemsTrvNodes.Add(cln);
this.treeView1.ItemsSource = itemsTrvNodes;




Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
public ClassNode()
//описание класса
	{
		//
		// TODO: добавьте логику конструктора
		//
        SubNodes = new List<ClassNode>();
        
    }   

    public int _IntTypeNode = new int();
 

    public int _IdNode = new int();

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



Как сделать выделение одного определенного узла дерева, причем он будет зависит от разных факторов.
...
Рейтинг: 0 / 0
14.01.2013, 16:18
    #38109547
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Можно ли как то выделить узел в дереве?
...
Рейтинг: 0 / 0
15.01.2013, 21:12
    #38111451
unknownfromrus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Solomka,

Поищи мой пост по TreeView. Я по нему очень много чего расписывал - а именно, изменение ControlTemplate. Дело в том что там будут подводные камни если оставить все как есть по умолчанию.
Я дмаю тебе не составит труда сделать небольшие изменения для добавления дополнительных тригеров для выделения.
А именно - добавь свое свойство булевского значения. Сажай в него логику выделения и добавляй его в MultiTriggers (Data). По идее ничего сложного нет
...
Рейтинг: 0 / 0
16.01.2013, 13:50
    #38112140
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
unknownfromrusSolomka,

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

Нашла твой пост /topic/982313&hl=
Только особо не поняла, как он может мне помочь.

Нашла в интернете пример Как выделить первый узел дерева:
Код: c#
\r\n        private void SelectFistItemInCatTreeView()\r\n        {\r\n            TreeViewItem item =\r\n                treeView1.ItemContainerGenerator.ContainerFromItem(treeView1.Items[0]) as TreeViewItem;\r\n            if (item != null)\r\n            {\r\n                item.IsSelected = true;\r\n            }\r\n            \r\n        }\r\n
\r\n
Этот код работает. Достаточно вызвать этот метод и сам узел выделится.

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

Код: c#
\r\n  private void SetSelectNodeTag(string varString)\r\n        {\r\n             for (int i = 0; i < treeView1.Items.Count; i++)\r\n            {\r\n                TreeViewItem item =\r\n                    treeView1.ItemContainerGenerator.ContainerFromItem(treeView1.Items[i]) as TreeViewItem;\r\n                 \r\n                SelectNodeTag03(varString, item);\r\n            }\r\n        }\r\n
\r\n

Метод SelectNodeTag по идее должен пробегать рекурсивно по всем узлам дерева, и если обнаружит искомый узел, то выделить его
Код: c#
\r\nprivate void SelectNodeTag03(string varString, TreeViewItem triCur)\r\n        {\r\n             \r\n            ClassNode nd = (ClassNode)triCur.Header; // здесь возникает ошибка при первом рекурсивном заходе\r\n            if (nd.Tag.ToString() == varString)\r\n            {\r\n                 \r\n                triCur.IsSelected = true;\r\n            }\r\n            else\r\n            {\r\n                for (int index = 0; index < triCur.Items.Count; index++)\r\n                {\r\n \r\n                    TreeViewItem searchItem = triCur.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem;\r\n                     \r\n                    TreeViewItem itemTreeViewItem = triCur.ItemContainerGenerator.ContainerFromItem(searchItem) as TreeViewItem;\r\n                    TreeViewItem itemTreeViewItem2 = triCur.ItemContainerGenerator.ContainerFromItem(triCur.Items[index]) as TreeViewItem;\r\n                    TreeViewItem itemTreeViewItem3 = treeView1.ItemContainerGenerator.ContainerFromItem(triCur.Items[index]) as TreeViewItem;\r\n                   // Все три переменные null\r\n                    SelectNodeTag03(varString, itemTreeViewItem);\r\n                }\r\n            }\r\n\r\n        }\r\n
\r\n
Однако если пользоваться ранее успешно примененной логикой, не удается "достать" хотя бы один подузел.
При первом же проходе в цикле for переменные "searchItem", "itemTreeViewItem", "itemTreeViewItem2", "itemTreeViewItem3" - имею пустые значения и в следующем первом рекурсивном заходе в метод возникает ошибка в строчке:
Код: c#
\r\nClassNode nd = (ClassNode)triCur.Header\r\n
\r\n
Что нельзя обращаться к NULL.

Причем если определить первый узел дерева превого уровня, например указав string temp = "1-169"; (169 - родительский для 171), то всё нормльно работает, потому что не пытается достать подузел.
...
Рейтинг: 0 / 0
16.01.2013, 18:02
    #38112716
unknownfromrus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Solomka,

Так давай по порядку.
Я правильно понимаю, что ты хочешь чтобы выделение узла в TreeView происходило не только по стандартным условиям, но ты еще свои добавишь (логику по которой должно происходить выделение)?
Мой пост тебе в помощь в том случае если ты захочешь переопределить Template у TreeView - так как возникнут подводные камни, о которых я там описывал.
В твоем же случае - чтобы добавить логику выделения - надо создать свойство, значение которого (Bool типа) будет определяться твоей логикой. И это свойство подцепить в условие IsSelected (найти его можно в Template - где определяется каким цветом и т.д. будет определяться выбранный узел). Так называемый MultiTrigger
...
Рейтинг: 0 / 0
17.01.2013, 10:21
    #38113388
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
unknownfromrusSolomka,

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

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

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

Если я правильно понимаю, то Template я так переопределяю...
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
                <sdk:TreeView.ItemTemplate >
                    
                    <sdk:HierarchicalDataTemplate ItemsSource="{Binding SubNodes}">
                    	<StackPanel>
                    		<TextBlock Text="{Binding FullHeader}" Tag="{Binding Tag}" />
                    	</StackPanel>                        
                    </sdk:HierarchicalDataTemplate>
                    
                </sdk:TreeView.ItemTemplate>



Если пишу сюда:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
            <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" установлено больше одного раза.

Куда надо прописать свойство, чтобы можно было выделать не только узлы первого уровня, но и большего уровня вложенности?
...
Рейтинг: 0 / 0
17.01.2013, 16:18
    #38114228
unknownfromrus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Solomka,

Расписывать че-то не хочется.
Давай сделаем так - дай мне свой примерчик что ты хочешь сделать - я его поправлю - добавив то что ты хочешь
...
Рейтинг: 0 / 0
21.01.2013, 15:51
    #38118234
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
unknownfromrusSolomka,

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

Ссылка на архив: http://yadi.sk/d/drPA-r0D20ITx
Не совсем родной проект, я его упростила, чтобы не отвлекать на сторонние вещи.
Слева дерево. справа список с ID узлов дерева.
И по ID надо выбрать узел в дереве.
...
Рейтинг: 0 / 0
23.01.2013, 15:00
    #38121521
enigmatic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
автор
Код: c#
1.
ClassNode nd = (ClassNode)triCur.Header

Что здесь происходит? Ты пытаешься взять Header из triCur, из типа TreeViewItem. Ты где-то до этого кладешь в Header ClassNode? Если ты этого не делаешь, то TreeViewItem'у в Header'е неоткуда взяться.

Насколько я вижу по коду, тебе нужно делать:
Код: c#
1.
ClassNode nd = (ClassNode)triCur.DataContext

а не то, что ты сейчас делаешь.

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

В-третьих, попробуй скачать проект по своей ссылке. У меня ничего не получилось.
...
Рейтинг: 0 / 0
24.01.2013, 09:05
    #38122673
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
enigmatic
В-третьих, попробуй скачать проект по своей ссылке. У меня ничего не получилось.

Странно, у меня всё получается.
На всякий случай ещё сюда выложила.
http://rapidshare.com/files/1787905320/wsTestSelectNodeToInet.zip
] http://rapidshare.com/files/1787905320/wsTestSelectNodeToInet.zip
...
Рейтинг: 0 / 0
24.01.2013, 09:22
    #38122684
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
enigmaticавтор
Код: c#
1.
ClassNode nd = (ClassNode)triCur.Header

Что здесь происходит? Ты пытаешься взять Header из triCur, из типа TreeViewItem. Ты где-то до этого кладешь в Header ClassNode? Если ты этого не делаешь, то TreeViewItem'у в Header'е неоткуда взяться.

Насколько я вижу по коду, тебе нужно делать:
Код: c#
1.
ClassNode nd = (ClassNode)triCur.DataContext

а не то, что ты сейчас делаешь.

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


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

Не очень понимаю, может ли мне это помочь.
Мне же надо чтобы выделенные узлы дерева менялись, в процессе работы и не были одним и тем же постоянным узлом...
...
Рейтинг: 0 / 0
24.01.2013, 10:54
    #38122792
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
enigmaticавтор
Код: c#
1.
ClassNode nd = (ClassNode)triCur.Header

Что здесь происходит? Ты пытаешься взять Header из triCur, из типа TreeViewItem. Ты где-то до этого кладешь в Header ClassNode? Если ты этого не делаешь, то TreeViewItem'у в Header'е неоткуда взяться.

Насколько я вижу по коду, тебе нужно делать:
Код: c#
1.
ClassNode nd = (ClassNode)triCur.DataContext

а не то, что ты сейчас делаешь.



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


возникает из-за того что мы в метод передаем переменную itemTreeViewItem2 NULL.
Код: c#
1.
 SelectNodeTag03(varString, itemTreeViewItem2);
...
Рейтинг: 0 / 0
24.01.2013, 12:18
    #38122948
enigmatic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
SolomkaЯ ничего не кладу в Header, я через отладку нашла, что это поле содержит информацию о экземпляре класса ClassNode.
Странно, по идее в Header'e не должно быть ClassNode, но ClassNode должен быть в DataContext'е triCur.

Solomkaenigmatic
Во-вторых, лучше не доставать из 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, то лучше выложи свой проект где-нибудь откуда скачать можно.
...
Рейтинг: 0 / 0
24.01.2013, 15:26
    #38123348
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
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
(тут есть кнопочка посмотреть и скачать и сохранить на яндекс.диск)
...
Рейтинг: 0 / 0
29.01.2013, 11:25
    #38128462
enigmatic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Solomka,

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

Во-вторых, сложно сказать почему именно не работает то, что ты хочешь. Просто код кошмарен и его проще переписать заново.
В теме уже указывалось как это лучше сделать.
unknownfromrusВ твоем же случае - чтобы добавить логику выделения - надо создать свойство, значение которого (Bool типа) будет определяться твоей логикой. И это свойство подцепить в условие IsSelected (найти его можно в Template - где определяется каким цветом и т.д. будет определяться выбранный узел).
...
Рейтинг: 0 / 0
04.02.2013, 09:03
    #38135684
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
enigmaticSolomka,

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

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

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

Кошмарен - не кошмарен... мой код... сказать сложно.
В интернете нашла пример с таким кодом
И он почти рабочий, для узлом первого уровня
...
Рейтинг: 0 / 0
06.02.2013, 13:10
    #38139830
Solomka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
unknownfromrusВ твоем же случае - чтобы добавить логику выделения - надо создать свойство, значение которого (Bool типа) будет определяться твоей логикой. И это свойство подцепить в условие IsSelected (найти его можно в Template - где определяется каким цветом и т.д. будет определяться выбранный узел). Так называемый MultiTrigger
Можете скинуть пример кода?
А то не совсем понятно...
...
Рейтинг: 0 / 0
07.02.2013, 11:19
    #38141297
unknownfromrus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Solomka,

Давай скидывай
...
Рейтинг: 0 / 0
10.02.2013, 15:18
    #38145079
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Сам недавно столкнулся с такой проблемой. Вроде бы выделить узел по его датаконтексту - не особенно трудный вопрос:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
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). Получилось вот так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
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 непосредственно, т.к. это сбросит биндинг свойства.
Ну, и в результате получаем
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
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 заставляет объект модели дерева возвращать все родительские узлы дерева от корня до требуемого элемента. Выглядит он так:
Код: c#
1.
2.
3.
4.
public interface ITraversable
{
  IEnumerable<object> Traverse { get; }
}


и реализуется рекурсией.
...
Рейтинг: 0 / 0
11.02.2013, 06:22
    #38145480
enigmatic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Сон Веры Павловны,

Хм, а зачем решать проблему на уровне контролов (TreeViewItem'ов), если можно объявить свойство IsSelected (+INPC) в модели и забиндиться на него?
...
Рейтинг: 0 / 0
11.02.2013, 09:45
    #38145560
Сон Веры Павловны
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
enigmaticХм, а зачем решать проблему на уровне контролов (TreeViewItem'ов), если можно объявить свойство IsSelected (+INPC) в модели и забиндиться на него?
Затем, что я писал выше:
Сон Веры ПавловныНо просто установки IsExpanded = true недостаточно - при этом только устанавливается значение DependencyProperty, а заполнение ItemsControl узлами происходит в отложенном порядке.
Аналогично без толку выставлять в true свойство модели, забинденное на IsExpanded - ItemContainerGenerator.ContainerFromItem(itemToSelect) будет возвращать null, т.к. ItemsControl узла на момент после установки свойства не заполнится соответствующими контролами. Это всё проверено на практике.
...
Рейтинг: 0 / 0
11.02.2013, 12:53
    #38145870
unknownfromrus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
Сон Веры Павловны,

Не знаю почему бестолку.
Недавно сделал тривью в комбобоксе. У меня были вложенные объекты. К объектам добавил свойство IsExpanded (поле класса объекта). Установил биндинг - и у меня разворачивается независимо от вложенности объектов (ЗАполнение объектов реализовано через HierarchiDataTemplate). Аналогично с IsSelected.
Вытаскивать из проекта Тривью я не хочу, чтобы тут выкладывать.
Тот кто поднимал тему - ему по ходу по фиг - раз до сих пор не выложил примерчик кода - я хотел попробовать в нем переопределить тривью
...
Рейтинг: 0 / 0
20.03.2013, 02:00
    #38190719
Obrazer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как сделать выделение одного узла в TreeView в Silverligth?
unknownfromrusУстановил биндинг - и у меня разворачивается независимо от вложенности объектов (ЗАполнение объектов реализовано через HierarchiDataTemplate). Аналогично с IsSelected.

А где биндинг делается и какого контрола? В HierarchiDataTemplate что-то или в самом TreeView?
...
Рейтинг: 0 / 0
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Как сделать выделение одного узла в TreeView в Silverligth? / 23 сообщений из 23, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]