DataType on TreeView - wpf

I'm trying to make some data binding on a TreeView in a WPF solution. However, I can't seem to figure it out.
my XAML is as follows:
<Window x:Class="NoteNest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Note Nest" Height="512" Width="756">
<DockPanel LastChildFill="True">
<StackPanel Width="190">
<TreeView HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="0" SelectedItemChanged="NoteSelect" DockPanel.Dock="Left" Name="Nest">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type Note}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</StackPanel>
</DockPanel>
</Window>
I keep getting the error:
Note is not supported in a Windows Presentation Foundation (WPF) project.
For the record. I have a public class named Note in the same namespace, so ether I have completely misunderstood how DataType works, or I'm just missing something.
What do I do?

Related

How to build Behavior Tree editor using WPF?

We are going to develop a behavior tree editor using WPF.
However, we are totally new to WPF.
How to generate shape components that represent tree nodes and the components should be able to respond to mouse event like right mouse clicked.
Do you have any suggestions on this?
You can specify different HierarchicalDataTemplate for your tree. They get chosen automatically by classname. You can also specify one for your base type. Be sure not to use interfaces, but real classes.
So if you use different classes for your view models you can get along with something like this:
<TreeView
ItemsSource="{Binding MyTreeVariable}"
SelectedItemChanged="MyTree_SelectedItemChanged">
<TreeView.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}" DataType="{x:Type self:MyBaseType}">
<StackPanel Orientation="Horizontal">
<Rectangle Width="16" Height="16"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}" DataType="{x:Type self:MySpecialType1}">
<StackPanel Orientation="Horizontal">
<Ellipse Width="16" Height="16"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}" DataType="{x:Type self:MySpecialType2}">
<StackPanel Orientation="Horizontal">
<!--- Triangle -->
<Polygon Points="50,0 100,100 0,100" Width="16" Height="16"/>
<TextBlock Text="{Binding Path=Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
If you like to tell the different behaviors by data, you can use DataTrigger and Setter, but I`d recommend the way shown above.

How to add icons to wpf treeview using dockpanel and binding?

I have a treeview inside of a dockpanel and all of the elements of the treeview are inside HierarchicalDataTemplates. Here is the code:
<DockPanel Margin="10,10,0,0" VerticalAlignment="Stretch" Grid.Row="0" Grid.RowSpan="5" Grid.Column="0">
<DockPanel.Resources>
<src:TreeViewFilter x:Key="MyList" />
<HierarchicalDataTemplate DataType="{x:Type src:TreeViewParent}" ItemsSource="{Binding Path=OrderAttributes}">
<TextBlock Text="{Binding Path=Name}" FontSize="24"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type src:OrderAttribute}" ItemsSource="{Binding Path=OrderAttributes}">
<TextBlock Text="{Binding Path=NameAndCount}" FontSize="16"/>
</HierarchicalDataTemplate>
</DockPanel.Resources>
<TreeView Name="treeView1" BorderThickness="2" ItemsSource="{Binding Source={StaticResource MyList}, UpdateSourceTrigger=PropertyChanged}" TreeViewItem.Selected="treeViewFilter"/>
</DockPanel>
As you can see, the DockPanel wraps around the TreeView. The icons I am trying to add would be in the second HierarchicalDataTemplate which binds to a string and displays as a textbox. Depending on the name of the "NameAndCount", I would choose an icon to be displayed next to it on the left.
Any ideas on a solution for my example? Or do I need to think about using different templates like StackPanel?
Add an Image-Control wherever you want, bind its Source to "NameAndCount" and use a IValueConverter to convert it to an image-path.

Are recursive DataTemplates possible?

I have a class something like:
public class Section
{
private IEnumerable<Section> sections;
private IEnumerable<KeyValuePair<string, string>> attributes
public string Name {get;set;}
public IEnumerable<Section> Sections
{
get {return sections;}
}
public IEnumerable<KeyValuePair<string, string>> Attributes
{
get {return attributes;}
}
public Section(...)
{
//constructor logic
}
}
Which is contained in another class, lets call it OtherClass for sake of argument, that wraps around it and is used in WPF in an ObjectDataProvider.
As you can see, an instance of Section can contain many other instances of Section.
Is there a way in XAML to create a template that deals with this recursion?
This is what I've got so far:
<UserControl x:Class="OtherClassEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:OtherClassNS="clr-namespace:NameSpace"
Height="300" Width="300">
<UserControl.Resources>
<ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" />
<DataTemplate x:Key="listViewAttr">
<WrapPanel>
<TextBlock Text="{Binding Path=Key}"></TextBlock><TextBlock Margin="0,0,4,0">: </TextBlock>
<TextBlock Text="{Binding Path=Value}"></TextBlock>
</WrapPanel>
</DataTemplate>
<DataTemplate x:Key="listViewSection">
<StackPanel>
<WrapPanel Margin="0,0,0,8">
<TextBlock Margin="0,0,4,0">Section:</TextBlock>
<TextBlock Text="{Binding Path=Name}"/>
</WrapPanel>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="listViewData">
<StackPanel>
<WrapPanel Margin="0,0,0,8">
<TextBlock Margin="0,0,4,0">Section: </TextBlock>
<TextBlock Text="{Binding Path=Name}"/>
<ListView DataContext="{Binding Path=Sections}" ItemTemplate="{StaticResource listViewSection}" ItemsSource="{Binding Sections}">
</ListView>
<ListView DataContext="{Binding Path=Attributes}" ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}">
</ListView>
</WrapPanel>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{StaticResource listViewData}" ItemsSource="{Binding Sections}">
</ListView>
</Grid>
</UserControl>
But I can't get recursion, as a DataTemplate can only reference one that is declared before it.
Can this be done in XAML? If so, how? Is this something that I'll have to do in code behind?
Are DataTemplates even the way to go? Is there a better way to display and edit this data?
In case anyone needs to see how to do this without using an HierarchicalDataTemplate:
<UserControl x:Class="OtherClassEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:OtherClassNS="clr-namespace:NameSpace"
Height="300" Width="300">
<UserControl.Resources>
<ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" />
<DataTemplate x:Key="listViewAttr">
<WrapPanel>
<TextBlock Text="{Binding Path=Key}"></TextBlock>
<TextBlock Margin="0,0,4,0">: </TextBlock>
<TextBlock Text="{Binding Path=Value}"></TextBlock>
</WrapPanel>
</DataTemplate>
<DataTemplate x:Key="listViewData">
<StackPanel>
<WrapPanel Margin="0,0,0,8">
<TextBlock Margin="0,0,4,0">Section: </TextBlock>
<TextBlock Text="{Binding Path=Name}"/>
</WrapPanel>
<ListView ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}" />
<ListView ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}">
</ListView>
</Grid>
</UserControl>
This gets me basically what I want.
The main change is as Dan Bryant suggested: changing the ItemTemplate to use a Dynamic rather than static resource for the recursive object (Section).
Perhaps I'm misunderstanding your scenario, but is HierarchicalDataTemplate what you're looking for?

WPF: Databinding and Combo Boxes

I have two classes
Company
CompanyKey
CompanyName
Person
FirstName
LastName
CompanyKey
The list items on the combo box is bound to a collection of CompanyObjects.
How to I databind the selected item property of the Combobox to the Person.CompanyKey property?
If I've understood your question correctly, here is a demo app that explains databinding of combo box: Demo App
Hope this helps.
Regards,
Mihir Gokani
EDIT: Fragment from code sample
<Window
x:Class="WpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
Height="300"
Width="300">
<StackPanel>
<TextBlock
Margin="10">Persons</TextBlock>
<ComboBox
x:Name="comboPersons"
Height="25"
Margin="10"
ItemsSource="{Binding Persons}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel
Orientation="Horizontal">
<TextBlock
Text="{Binding FirstName}"
Margin="0,0,5,0" />
<TextBlock
Text="{Binding LastName}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock
Margin="10">Companies</TextBlock>
<ComboBox
x:Name="comboCompanies"
Height="25"
Margin="10"
ItemsSource="{Binding Companies}"
DisplayMemberPath="CompanyName"
SelectedValuePath="CompanyKey"
SelectedValue="{Binding SelectedItem.CompanyKey, ElementName=comboPersons}" />
</StackPanel>
</Window>
The solution is simple, you need to use an IValueConverter to convert to Company to the Person object.
For more information on IValueConverter, please see:
http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx
You can then bind it in your xaml with something like:
{Binding Path=combox.SelectedItem, Converter={StaticResource CompanyToPersonConvertor}}

Does any one know of an exhaustive collection of WPF databinding examples?

It seems that every time I read an article on "how to do WPF data binding", it is done with some different variation, sometimes with DataContext, sometimes without, sometimes with Itemssource or both Itemssource and DataContext, there's also ObjectDataProvider, and you can have any of these in XAML or codebehind, or no codebehind and bind directly from XAML to your ViewModels.
It seems like there are dozens of different syntaxes to use within the XAML itself, e.g.:
<ListBox ItemsSource="{Binding Source={StaticResource Customers}}">
and
<ListBox DataContext="{StaticResource Customers}" ItemsSource="{Binding}">
These two code samples, for example, do the same thing:
1. Using ObjectDataProvider with no code-behind:
<Window x:Class="TestDataTemplate124.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestDataTemplate124"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ObjectDataProvider x:Key="Customers"
ObjectType="{x:Type local:Customer}"
MethodName="GetAllCustomers"/>
</Window.Resources>
<StackPanel>
<ListBox DataContext="{StaticResource Customers}" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding LastName}"/>
<TextBlock Text=" ("/>
<TextBlock Text="{Binding Age}"/>
<TextBlock Text=")"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
2. Example with no DataContext:
<Window x:Class="TestDataTemplate123.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestDataTemplate123"
Title="Window1" Height="300" Width="300">
<StackPanel>
<ListBox x:Name="ListBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding LastName}"/>
<TextBlock Text=" ("/>
<TextBlock Text="{Binding Age}"/>
<TextBlock Text=")"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>
using System.Collections.ObjectModel;
using System.Windows;
namespace TestDataTemplate123
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
ListBox1.ItemsSource = Customer.GetAllCustomers();
}
}
}
Does anyone know of a source that explains WPF Databinding by instead of just saying "here's how you do databinding" and then explain one particular way, but instead attempt to explain the various ways to go about databinding and show perhaps what the advantages and disadvantages of e.g. having DataContext or not, binding in XAML or code-behind, etc.?
Check out this cheatsheet
I can recommend you the blog from Bea Stollnitz. If I'm not mistaken, she works at Microsoft and is involved in the development on WPF, particularly in databinding. She really has some great WPF tutorials, many on databinding. You should find some really good info here.

Resources