Building up ExplorerBar via ItemsSource and DataTemplate

Navigation for WPF Forum

Posted 15 years ago by Michael Hays - Owner, Spiral LLC
Version: 4.5.0480
Avatar
I am dynamically building the content of an ExplorerBar, and I was hoping that there was already some clever way to bind to a resource and use data templates to construct the menu items and Expanders.

I tried the following (some snippage has occurred):

-----------------------
<Window.Resources>

<DataTemplate x:Key="ExpItem">
<TextBlock Text="{Binding XPath=@name}"/>
</DataTemplate>

<DataTemplate x:Key="Exp">
<shared:AnimatedExpander IsExpanded="True" Header="{Binding XPath=@name}">
<ItemsControl ItemsSource="{Binding XPath=b}"
ItemTemplate="{StaticResource ExpItem}"/>
</shared:AnimatedExpander>
</DataTemplate>

</Window.Resources>

<Grid>
<ItemsControl VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Grid.Column="0" Grid.Row="0" x:Name="MyExplorerBar"
ItemsSource="{Binding Source={StaticResource SomeXmlData}, XPath=/Menu/a}"
ItemTemplate="{StaticResource Exp}"/>
</Grid>
-----------------

This works. But if I replace ItemsControl with nav:ExplorerBar, it turns up empty. Is there some other way?

Comments (12)

Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Michael,

There are actually two issues with this. The first issue was that the ExplorerBar was not using the ItemTemplate and ItemTemplateSelector. Therefore, in your code above the ItemTemplate property setting was being ignored. This has been fixed for the next maintenance release, and we have added a QuickStart on populating the ExplorerBar using an XML datasource.

The second issue is with your DataTemplate. Assuming it was being used (with the first issue fixed), it would be applied to the header of the Expander container. So with the code you have above, you would end up with an Expander with no content, but with a header that contains an AnimatedExpander. Regardless, you can take a look at the new QuickStart to see how to do this.


Actipro Software Support

Posted 15 years ago by Michael Hays - Owner, Spiral LLC
Avatar
Thank you for your previous post. I have returned to pretty up this part of the application :-)

Using the new version of ExplorerBar does allow me to use ItemsSource and ItemContainerStyle (woohoo!), but I am unable to create a style that targets AnimatedExpander -- I have to target an Expander. I'm trying to set things like CornerRadius, HeaderForegroundNormal, et al of the header in the style, but unfortunately, these are properties of AnimatedExpander. Replacing HeaderTemplate seems like it will blow away all the Animation abilities (I'm using themes:ExplorerBarLunaNormalColorDictionary.ExpanderStyleKey).

Is there some other way to affect changes like this? I mean, ultimately I would love to just provide a DataTemplate that specifies AnimatedExpander directly. Am I missing something obvious?

(You know... I really could forgo using an explorer bar at all if I would just program my own style that enforces CanExpandMultiple="False" on its children... hmmmmm...).

[Modified at 02/16/2009 11:07 PM]
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Michael,

Would it help if we just override our ExplorerBar to use AnimatedExpanders for item containers instead of standard WPF Expanders?


Actipro Software Support

Posted 15 years ago by Michael Hays - Owner, Spiral LLC
Avatar
If the expanders are necessarily going to be AnimatedExpanders, then you might as well.

But now, what if it were possible for the user to provide his or her own subclass of expander? Have an event called "CreateExpander" on the ExplorerBar. The user can optionally catch this event, provide their own expander, mark a handled flag and an optional OverrideStyle flag. Then the sky is the limit, and you can leave your current implementation choices as they are (although frankly, your AnimatedExpander is much nicer than the vanilla Expander, I would probably still use that as the default -- why make it even one character harder to use your stuff).

Darn, I should have bought the blueprint version... I would just code this up.
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Actually all you need to do is add this to ExplorerBar or an ExplorerBar override:
/// <summary>
/// Creates or identifies the element used to display a specified item. 
/// </summary>
/// <returns>A <see cref="Expander"/>.</returns>
protected override DependencyObject GetContainerForItemOverride() {
    return new AnimatedExpander();
}

/// <summary>
/// Determines if the specified item is (or is eligible to be) its own item container.
/// </summary>
/// <param name="item">Specified item.</param>
/// <returns>
/// <c>true</c> if the item is its own item container; otherwise, <c>false</c>.
/// </returns>
protected override bool IsItemItsOwnContainerOverride(object item) {
    return (item is AnimatedExpander);
}


Actipro Software Support

Posted 15 years ago by Michael Hays - Owner, Spiral LLC
Avatar
Neeeeeet! Thank you, this worked great.
Posted 15 years ago by Greg Larson
Avatar
I am also trying to use DataTemplates to populate the ExplorerBar. I am getting the AnimatedExpander in both the Header AND Content.

You mentioned looking at the QuickStart to how to do this properly, but I see nothing related to DataTemplates in the samples for ExlorerBar and AnimatedExpander. Can you be more specific or provide an example?

Thanks!
Greg
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Greg,

The QuickStart referred to by this thread is under the Navigation section of our Sample Browser and is titled "ExplorerBar Bound Items". It uses XML data and DataTemplates to populate the ExplorerBar.

If that doesn't help, please email over a small sample project to our support address and we can take a look.


Actipro Software Support

Posted 15 years ago by Greg Larson
Avatar
Thanks. I found it and have it working. It's unfortunate though that I have to use a code-behind StyleSelector and not be able map my ViewModel object directly to a DataTemplate with 'DataTemplate DataType=' in XAML.

Thanks again for the prompt reply.
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Greg,

The ExplorerBar is just a fancy Selector/ItemsControl. It uses the AnimatedExpander as a container for it's items, just like the ListBox uses ListBoxItem. Now the AnimatedExpander is a HeaderedContentControl, so ultimatley we need to set the Content (including ContentTemplate and ContentTemplateSelector) and the Header (including HeaderTemplate and HeaderTemplateSelector) properties.

So when loading data (such as an XmlElement) in the ExplorerBar, you need a mechanism to set both the Content and the Header. The only way to do this is to use a custom Style that targets the Expander type (which also encompasses the AnimatedExpander type). The sample uses a StyleSelector, since there are two different looks (normal and alternate) and we want to switch them based on an attribute of the XmlElement. But if you only want to use one "look" you can assign a single Style to the ItemContainerStyle property.

So ultimately you can use implicit DataTemplates for displaying the Content and Header, but not to assign the Header property (that needs to be done explicitly).


Actipro Software Support

Posted 15 years ago by Greg Larson
Avatar
Thanks. This is what I assumed was happening after seeing the Style. Originally I was using an ItemsControl and provided DataTemplates for items. The DataTemplate simply contained an Expander containing a UserControl.

Since ExplorerBar is an ItemsControl containing AnimatedExpanders, is seems like replacing ItemsControl with ExplorerBar and Expander (in the DataTemplates) with AnimatedExpander, all should work the same. Perhaps it is because ExplorerBar is already creating AnimatedExpanders and not just using whatever is in the DataTemplate?
Posted 15 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Greg,

That's correct. The ItemsControl.GetContainerForItemOverride returns a ContentPresenter, which means the data item will be set to the Content and you can use implicit DataTemplates. The ExplorerBar on the other hand returns AnimatedExpander from the method above.

So if you add a String to the ItemsControl, a ContentPresenter is created, it's Content is assigned the String. Then the String is displayed using an implicit DataTemplate. If you add a String to an ExplorerBar, an AnimatedExpander is created, and again it's Content is set and displayed using an implicit DataTemplate. But the Header is never set, so it's not completely setup.


Actipro Software Support

The latest build of this product (v24.1.2) was released 1 days ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.