Does ContentPresenter.ContentTemplate supports HierarchicalDataTemplate(WPF)? - wpf

I have gone through the HierarchicalDataTemplate in the document, in which it is mentioned that "DataTemplate that supports HeaderedItemsControl". From this point, I understood that HierarchicalDataTemplate is supported for the control which is derived from HeaderedItemsControl (That is to display collection of items). Right?
Now, I just want to confirm that, is there any possible way to load HierarchicalDataTemplate as ContentPresenter.ContentTemplate(WPF) and display items in hierarchical way?
As like below code snippet
<ContentPresenter>
<ContentPresenter.ContentTemplate>
<HierarchicalDataTemplate>
..........
..........
..........
</HierarchicalDataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>

Related

Can I bind to an ancestor DataTemplate in Silverlight?

I'm having trouble pulling off a binding that I believe should be valid in Silverlight 5:
<Controls:GraphLayout>
<Controls:GraphLayout.VertexTemplate>
<DataTemplate>
<TextBox ... />
</DataTemplate>
</Controls:GraphLayout.VertexTemplate>
<Controls:GraphLayout.SubgraphTemplate>
<DataTemplate>
<Controls:GraphLayout VertexTemplate="{Binding VertexTemplate, RelativeSource={RelativeSource AncestorType=Controls:GraphLayout}}"/>
</DataTemplate>
</Controls:GraphLayout.SubgraphTemplate>
</Controls:GraphLayout>
This is a simplified example but hopefully it's pretty readable. In excessence I'm trying to bind the VertexTemplate of the SubgraphTemplate to the VertexTemplate of the containing control (the root GraphLayout control). Unfortunately, in the code behind I can see that VertexTemplate is null in the subgraph control.
May be your code can work (this is strange that you bound to something that doesn't have an x:Key and I think you should use {StaticResource SomethingWithName})).
But actually what you looking for is DataTemplateSelector. It's very easy to use and actually support the logic you described.

Setting the background color of separate WPF ListBox items

I want to set the background color separately for each item in a WPF ListBox. e.g. If I am adding Widgets to the ListBox, I might set the background color for each one based on the type of widget. This must be done in code (not XAML) as I only know what the items are at run time.
I know how to use ItemContainerStyle to set the style for all items, but how do you do it separately for each item?
Yes you do set ItemContainerStyle, using a StyleSelector.
This example at MSDN is exactly what you are looking for.
There are lots of ways to do this.
One is to use a StyleSelector, as loxxy suggests. This is pretty low on my list, because that kind of code is harder to read (well, find) and test than I'd like.
Another is to use a DataTrigger in the style. This is simple, if (and only if) the items all implement a common property that can be used in the trigger. You might be well served by implementing a wrapper class that exposes this common property, and contains the logic that figures out what value to assign to the property based on the object it's wrapping. (Whether or not this is easier than a StyleSelector is certainly arguable.)
If the items are really and truly heterogeneous, you can accomplish the result by using data templates, e.g.:
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:Foo}">
<TextBlock Text="{Binding FooText}" Background="Red"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Bar}">
<TextBlock Text="{Binding BarText}" Background="Yellow"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Baz}">
<TextBlock Text="{Binding BazText}" Background="PapayaWhip"/>
</DataTemplate>
</ListBox.Resources>
etc. This would generally be my first choice, but your question doesn't really explain enough about the circumstances to know if it's the right way to go or not.

Should I be using UserControls for my Views instead of DataTemplates?

I was reading this post and the author makes the suggestion that using DataTemplates to define a ViewModel is a lunatic's way to do it (#7). I do that all the time, is it really that bad?
<DataTemplate DataType="{x:Type local:MyViewModel}">
<Grid>
...
</Grid>
</DataTemplate>
Most of my Views are simply a ResourceDictionary that defines a DataTemplate or two. To me, it makes much better sense to do this than creating a UserControl for every ViewModel. Why would I want the extra layer in WPF's visual tree when it's not needed? And why would I want to take care of mapping ViewModels to Views when a DataTemplate does that for me? Is this syntax really a "lunatics approach"?
Nothing bad about it, except for incredibly large xaml files and the lack of edit support that DataTemplates have on the design surface.
If those issues are hurting you, you can always...
<DataTemplate DataType="{x:Type local:MyViewModel}">
<local:MyViewModelUserControl />
</DataTemplate>
The good thing with DataTemplate is that they are strongly typed to Viewmodel classes. All you need to do is create a ContentPresenter in View and Bind DataContext to VM. If your DataTemplate is defined in a ResourceDictionary and has a DataType attribute instead of Key, WPF will internally figure out the right DataTemplate for the VM class and display it.
But as you mentioned, we cannot create the DataTemplate in a seperate file. So the file where the DataTemplates exist in ResourceDictionary (e.g. App.xaml), the file gets really messy and it becomes difficult to manage the code soon.
So my take is, if the VM is simple create a DataTemplate. Or else it is always better to create a seperate UserControl and bind its content to the VM.
I run into the issue with performance. There is difference between next two case:
1.
<DataTemplate DataType="{x:Type local:MyViewModel}">
<!-- xaml is moved to separate user control -->
<local:MyViewModelUserControl />
</DataTemplate>
2.
<DataTemplate DataType="{x:Type local:MyViewModel}">
<!-- xaml is typed here directly -->
<Border>
...
</Border>
</DataTemplate>
In 1st case it takes longer to render results than in the 2nd. And this difference is in about 2 times.
I posted it as a separate question

Can I databind to properties of a custom class (instantiated in xaml) that then forms the content of a templated listboxitem

Any help on this really appreciated. In summary I'm trying to databind to properties of a custom class instantiated in xaml that then forms the content of a templated listboxitem (phew!).
I have a simple c# class called MenuItem. It has two properties:
- Heading
- Icon
Concentrating on just one of those menu items (i.e. to provide a simple example of where I am stuck) If I do this (with the values hard coded) it works fine:
<ListBox>
<ListBoxItem ContentTemplate="{StaticResource MenuItemTemplate}">
<myclasses:MenuItem Heading="News" IconImage="News.png"/>
</ListBoxItem>
</Listbox>
Where MenuItemTemplate is an appropriate DataTemplate in the resources section binding each property) containing lines such as:
<TextBlock x:Name="tbHeading" Text="{Binding Heading}">
Wheareas when I try to use binding to set the Heading property it falls over (AG_E_PARSER_BAD_PROPERTY_VALUE error)- e.g.:
<ListBox>
<ListBoxItem ContentTemplate="{StaticResource MenuItemTemplate}">
<myclasses:MenuItem Heading="{Binding NewsHeading, Mode=OneWay}" Icon="News.png"/>
</ListBoxItem>
<Listbox>
I've wondered if it is because I'm doing some kind of double binding (i.e. the template is binding to a value on the MenuItem class that needs to be bound) and that's not possible? I've tried having the properties declared as dependency properties but no difference (although I only learned about those today so I may be missing something).
I know I could set the menuitem objects up in the view model, and bind from there, but I would like to understand why the above doesn't work (as for my purposes there are advantages in constructing the menu items in the xaml).
Thank you!!!!
Ian
thanks for sticking with this. I agree the listbox might not be needed - but even if I reduce it to just one item in a contentcontrol:
<ContentControl ContentTemplate="{StaticResource MenuItemTemplate}">
<myclasses:MenuItem Heading="{Binding NewsHeading, Mode=OneWay}" IconImage="News.png"/>
</ContentControl>
I still have the same problem - which is that I can get databinding to work within the content of a contentcontrol (prior to it being presented by the datatemplate referred to in ContentTemplate) using purely xaml.
I.e. the above bit of xaml doesn't work - it throws an error on the bit that binds the NewsHeading:
Heading="{Binding NewsHeading, Mode=OneWay}
So I am trying to understand whether what I'm doing is impossible, or whether it is but I'm doing it wrong.
Thanks.
Assuming that you have multiple MenuItem classes (because you're putting them in a listbox and ti wouldn't make sense to do that if you just had one). You need to bind the collection to the ItemsSource property of the ListBox.
Somehting like this:
<ListBox ItemsSource="{Binding MyMenuItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Heading}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note that the above assumes you've set the DataContext on the page to an object with a property called MyMenuItems which is a collection of your MenuItem objects.
To see a full example of this, look at the default code created when you create a new "Windows Phone Databound Application".
Edit:
Based on your comments, it seems that a ListBox is not the most appropriate solution to your needs. A ListBox is designed/intended to take a collection of items and display them in a list.
If you have a number of different objects which you know about at design time and simply wish to have them one on top of another (giving the appearance of a list) you could simply put them inside a ScrollViewer and/or a StackPanel (or other appropriate container). Plus, you would still be able to databind if you did it this way.

Can I create a navigation control like this example in WPF using a TreeView?

I want to create a WPF control similar to the example below. Check out the link and look at the navigation control on the left.
Can this be done in a treeview? If so, any idea how I would start?
If not a treeview, then how could I achieve the same thing?
Navigation example
The parent node has a different style to the child node and in some cases a parent will have child nodes and some won't. I'm not sure how to style a control that will give me the same look. Any advice would be greatly appreciated.
Thanks,
Since you can style different nodes of a treeview as you like, the answer is yes, you can. You have to bind a treeview to an IEnumerable<A>, where every object of type A will have an IEnumerable<B> (which can be empty).
You can then apply one style to every element of type A, and another style to every element of type B. In XAML, in TreeView.Resources, put two HierarchicalDataTemplates with DataType attributes. For example, if you have an IEnumerable of Categories, and each Category has a property Items which is an IEnumerable of Items, you may write:
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type core:Category}">
<!--Content here-->
<HierarchicalDataTemplate.ItemsSource>
<Binding Path="ContextAssociations"/>
</HierarchicalDataTemplate.ItemsSource>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type core:Item}">
<!--Content here-->
</HierarchicalDataTemplate>
</TreeView.Resources>

Resources