#c# #wpf #xaml #treeview #xmldataprovider
#c# #wpf #xaml #просмотр дерева #xmldataprovider
Вопрос:
У меня есть WPF TreeView
, который был заполнен из XML-файла во время выполнения. Я нажимаю на кнопку, и появляется FileDialog
поле, а затем я выбираю XML-файл. Затем XML-файл загружается в TreeView
. Я использовал a XmlDataProvider
и некоторые HierarchicalDataTemplate
s для загрузки XML.
Я добавил обработчик действий с TreeView, но когда я выбираю элемент этого TreeView, я не могу найти никакой ссылки на этот элемент. Я нахожу ссылку только на первый элемент.
Как я могу решить эту проблему?
XAML является:
<Window x:Class="Demo2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="800">
<Window.Resources>
<XmlDataProvider x:Key="MEIInformation" XPath="/MEI" />
<HierarchicalDataTemplate DataType="Case" ItemsSource="{Binding}">
<TextBlock Text="{Binding XPath=@Name}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Phase" ItemsSource="{Binding}">
<TextBlock Text="{Binding XPath=@Name}"></TextBlock>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Trigger" ItemsSource="{Binding}">
<TextBlock Text="{Binding XPath=@Name}"></TextBlock>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<ToolBarTray>
<ToolBar>
<Button ToolTip="Open Test Suite" Click="OpenTestSuite">
<Image Source="Icons/open.png"></Image>
</Button>
</ToolBar>
</ToolBarTray>
<TreeView x:Name="trv" FontSize="14" Height="518" HorizontalAlignment="Left" Margin="6,31,0,0" VerticalAlignment="Top" Width="431">
<TreeViewItem ItemsSource="{Binding Source={StaticResource MEIInformation}, XPath=*}" Header="Suites"></TreeViewItem>
</TreeView>
</Grid>
</Window>
И фрагмент кода является:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.trv.MouseRightButtonUp =new MouseButtonEventHandler(DoSomething);
}
private void OpenTestSuite(object sender, RoutedEventArgs e)
{
XmlDocument xmlDocument = new XmlDocument();
OpenFileDialog open = new OpenFileDialog();
open.Filter = "XML Files (*.xml)|*.xml";
if (open.ShowDialog() == true)
{
xmlDocument.Load(open.FileName);
XmlDataProvider dataProvider = this.FindResource("MEIInformation") as XmlDataProvider;
dataProvider.Document = xmlDocument;
}
}
private void DoSomething(object sender, MouseEventArgs e)
{
MessageBox.Show("Do Something in TreeView!");
TreeViewItem childItem = e.Source as TreeViewItem;
if (childItem != null)
{
MessageBox.Show(childItem.Header.ToString()); // or MessageBox.Show(childItem.toString);
childItem.IsSelected = true;
}
else
MessageBox.Show("No Selected Item!");
}
}
XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<MEI>
<Case Name="Jean Price">
<Phase Name="January">
<Trigger Name="Order # JAN001"></Trigger>
<Trigger Name="Order # JAN002"></Trigger>
</Phase>
<Phase Name="February">
<Trigger Name="Order # FEB001"></Trigger>
</Phase>
</Case>
<Case Name="John P Grant">
<Phase Name="April">
<Trigger Name="Order # APR001"></Trigger>
<!-- ... -->
</MEI>
Я просто хочу иметь ссылку на этот элемент, чтобы я мог добавить новый элемент после этого элемента.
@Mart Я изменил представление дерева в xaml следующим образом … (добавил SelectedItemChanged=»doSomething»)…
<TreeView SelectedItemChanged="DoSomething"....../>
И теперь код c # готов…….
private void DoSomething(object sender, EventArgs e)
{
MessageBox.Show("Do Something in TreeView!");
TreeViewItem childItem = sender as TreeViewItem;
if (childItem != null)
{
MessageBox.Show(childItem.Header.ToString());
childItem.IsSelected = true;
MessageBox.Show("It Works!");
}
else
MessageBox.Show("No Selected Item!");
}
но совсем не повезло. И я не понял предложение вашего пользовательского интерфейса …:(
Комментарии:
1. Не могли бы вы, пожалуйста, вставить сюда фрагмент вашего кода, чтобы мы могли выяснить, что именно пошло не так
2. xml-это: XML-файл: <?xml version= «1.0» encoding = «ISO-8859-1»?> <MEI> <Имя обращения = «Цена Джин»> <Название фазы = «Январь»> <Имя триггера= «Заказ # JAN001″> </Trigger> <Имя триггера=»Заказ # JAN002″> </Trigger> </ Phase> <Имя фазы=»Февраль»> <Имя триггера= «Заказ № FEB001»> </Trigger> </Phase> </Case> <Имя дела= «Джон П. Грант»> <Название фазы= «Апрель»> <Имя триггера= «Заказ № APR001»> </Trigger> <Имя триггера= «Заказ № APR002″> </Trigger> </Phase> <Название фазы=»Май»> <Имя триггера= «Заказ № MAY001»> </Trigger> </Phase> </Case> </MEI>
Ответ №1:
Это способ, который я нашел для получения selectedTreeViewItem
значения, я получил его от xmlElement
.
Учитывая этот код xaml:
<i>
<Window.Resources>
<HierarchicalDataTemplate DataType="Filial"
ItemsSource="{Binding XPath=./*}">
<StackPanel Orientation="Horizontal">
<Image Source="/WpfClient;component/Images/image4.png"
Height="20"></Image>
<TextBlock Margin="5,0,0,0"
Text="{Binding XPath=@name}"
FontSize="18"
FontFamily="BankGothic Md BT"
Foreground="#FF355CE5"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="Setor"
ItemsSource="{Binding XPath=./*}">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5,0,0,0"
Text="{Binding XPath=@name}"
FontWeight="Bold" />
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="User">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding XPath=@source}"
Height="15"></Image>
<TextBlock Margin="5,0,0,0"
Text="{Binding XPath=@name}"
FontStyle="Italic" />
</StackPanel>
</HierarchicalDataTemplate>
<XmlDataProvider x:Key="xmlDP"
Source="Contatos.xml"
XPath="/Contatos/Filial"></XmlDataProvider>
</Window.Resources>
<Grid Width="Auto"
Height="Auto">
<TreeView Name="tv"
ItemsSource="{Binding }"
DataContext="{StaticResource xmlDP}"
Margin="0,0,0,0"
TreeViewItem.Selected="tv_Selected">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="TreeViewItem.IsExpanded"
Value="True" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</Grid>
</i> </pre>
и этот c # codebehind:
private void tv_Selected(object sender, RoutedEventArgs e)
{
System.Xml.XmlElement xmlElement= (XmlElement)tv.SelectedItem;
string mySelectedValue = xmlElement.Attributes[0].Value.ToString();
MessageBox.Show(mySelectedValue , "SelectedTreeValue", MessageBoxButton.OK, MessageBoxImage.Information);
}
</i>
и это XML-файл:
<i>
<?xml version="1.0" encoding="utf-8" ?>
<Contatos>
<Filial name="Firm">
<Setor name="Sector 1">
<User name="user1" source="/WpfClient;component/Images/user.png"></User>
<User name="user2" source="/WpfClient;component/Images/user.png"></User>
<User name="user3" source="/WpfClient;component/Images/admin.png"></User>
</Setor>
<Setor name="Sector40">
<User name="user43" source="/WpfClient;component/Images/admin.png"></User>
<User name="user44" source="/WpfClient;component/Images/user.png"></User>
<User name="user45" source="/WpfClient;component/Images/user.png"></User>
<User name="user46" source="/WpfClient;component/Images/user.png"></User>
</Setor>
</Filial>
</Contatos>
</i>
Комментарии:
1. Для дальнейшего использования: просто имейте в виду, что TreeViewItem. Выбранный не отображается через intellisense.
Ответ №2:
Я не вижу, что запускает ваш DoSomething
обработчик, я предполагаю, что он реагирует на Click
событие.
Если это щелчок по элементу шаблона элемента, вы можете не получить правильный параметр отправителя.
Вы можете привести отправителя к UIElement
, а затем получить доступ к его DataContext
, который должен быть одним из ваших XML-элементов.
Другой способ — отреагировать на SelectionChanged
событие treeview, которое предоставит вам элемент treview в аргументах события.
Комментарии:
1. На самом деле это.trv.MouseRightButtonUp =новый MouseButtonEventHandler (doSomething); запускает метод doSomething….
2. Выполнение подобным образом не даст вам элемент treeview в качестве контекста, но treeview. Вы можете получить доступ к своему элементу, если он выбран (щелчок правой кнопкой мыши не обязательно выбирает элемент) с помощью trv.SelectedItem.
3. В вашем обработчике событий SelectionChanged установите точку останова и обратите внимание на тип объекта sender и e.Source. Эти объекты зависят от того, как вы разместили свои обработчики. Затем приведите их правильно и следуйте моему предложению выше.
4. Итак, ваш вопрос скорее «Как отобразить контекстное меню в моих элементах treeview?». Вы должны добавить истинное ContextMenu в свой HierarchicalDataTemplate, как описано здесь: wpftutorial.net/ContextMenu.html
5. Если вы хотите добавить подпункты в свой treeview, рекомендуемый способ — воспользоваться привязкой к данным: добавьте элементы в свой XML, и они должны отразиться в treeview. В противном случае взгляните на ItemContainerGenerator и его методы ItemFromContainer и ContainerFromItem.