- Nir Hasson
- Posts: 71
- Joined:
- Contact:
Invoke Storyboard on specific DataTemplate Instance
I have an ItemsControl that holds multiple items with a custom DataTemplate as the ItemTemplate property.
On my model-view code I have a data manager that holds list of visible items bounded to the ItemsSource property of the ItemsControl.
The display screen can't show all items so I'd like to create some cross fade in/out animation that will be applied on certain item. I would like to play the animation and at the end of it I would like to change the content of the data collection to hold new set of data items to be displayed.
I've manage to create a Storyboard within the scope of my DataTemplate.Resources but from this point I'm kinda lost ...
Any suggestions to accomplish this task would be great..
Thanks
On my model-view code I have a data manager that holds list of visible items bounded to the ItemsSource property of the ItemsControl.
The display screen can't show all items so I'd like to create some cross fade in/out animation that will be applied on certain item. I would like to play the animation and at the end of it I would like to change the content of the data collection to hold new set of data items to be displayed.
I've manage to create a Storyboard within the scope of my DataTemplate.Resources but from this point I'm kinda lost ...
Any suggestions to accomplish this task would be great..
Thanks
Re: Invoke Storyboard on specific DataTemplate Instance
Hey, see if this example helps: http://stackoverflow.com/questions/4267 ... -a-user-co
-
sfernandez
Site Admin
- Posts: 2997
- Joined:
Re: Invoke Storyboard on specific DataTemplate Instance
As I explained in a previous post, you can obtain the container of your data item. Then you can apply the storyboard to that container:
Code: Select all
void ApplyStoryboard(BaseComponent dataItem, Storyboard storyboard)
{
FrameworkElement element = FindContainerFromItem(dataItem).As<FrameworkElement>();
if (element != null)
{
storyboard.Completed += this.OnAnimationCompleted;
storyboard.Begin(element);
}
}
void OnAnimationCompleted(BaseComponent sender, TimelineEventArgs e)
{
Storyboard storyboard = sender.As<Storyboard>();
if (storyboard != null)
{
storyboard.Completed -= this.OnAnimationCompleted;
// do something
}
}
- Nir Hasson
- Posts: 71
- Joined:
- Contact:
Re: Invoke Storyboard on specific DataTemplate Instance
The suggested implementation didn't work for me.
Here is the code I used to grab ListBoxItem from the DataItem.
When I use it that way the ItemsPanel is never found although I explicitly declare it in the XAML code.
I'm getting a Panel object but the GetIsItemsHost condition fails.
When I force the first found Panel to be selected as ItemsPanel I'm getting fixed number of 8 items in the element collection object and it never finds the container item.
Please advice.
Nir
Here is the code I used to grab ListBoxItem from the DataItem.
Code: Select all
//-----------------------------------------------------------------------------
Noesis::Gui::ListBoxItem* NoesisGUIUtils::ListBoxItemFromDataItem(Noesis::Gui::ListBox* pListBox, Noesis::Core::BaseComponent* pDataItem)
{
// Assuming you named ItemsHost panel in your ListBox template
// Otherwise, you have to find it iterating ListBox children with
// VisualTreeHelper,and looking for a Panel with the IsItemsHost
// property set to true
Noesis::Gui::Panel* pItemsPanel = NULL;
for (NsSize nVisualChild=0; nVisualChild < Noesis::Gui::VisualTreeHelper::GetChildrenCount(pListBox); ++nVisualChild)
{
Noesis::Gui::Visual* pCurVisualChild = Noesis::Gui::VisualTreeHelper::GetChild(pListBox, nVisualChild);
Noesis::Gui::Panel* pCurPanel = NsDynamicCast<Noesis::Gui::Panel*>(pCurVisualChild);
if (pCurPanel != NULL && pCurPanel->GetIsItemsHost())
{
pItemsPanel = pCurPanel;
break;
}
}
if (pItemsPanel == NULL)
{
return NULL;
}
Noesis::Gui::UIElementCollection* pCollection = pItemsPanel->GetChildren();
// Search the requested list box item
NsSize numItems = pCollection->Count();
for (NsSize i = 0; i < numItems; ++i)
{
Noesis::Core::BaseComponent* container = pCollection->Get(i);
Noesis::Gui::ListBoxItem* pListBoxItem = NsStaticCast<Noesis::Gui::ListBoxItem*>(container);
// ListBoxItem contains the instantiation of data template visual tree
Noesis::Gui::FrameworkElement* element = NsStaticCast<Noesis::Gui::FrameworkElement*>(
pListBoxItem->GetContent());
// Data item is set as DataContext of the DataTemplate root element
if (element != NULL && element->GetDataContext() == pDataItem)
{
// Found!! :)
return pListBoxItem;
}
}
// Data item not found
return NULL;
}
I'm getting a Panel object but the GetIsItemsHost condition fails.
Code: Select all
<ListBox x:Name="SourceListBox"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource MyItemTemplate}" Width="400" HorizontalAlignment="Left" Height="600">
<ListBox.ItemsPanel>
<ItemsPanelTemplate x:Name="ItemsHostPanel">
<StackPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
Please advice.
Nir
-
sfernandez
Site Admin
- Posts: 2997
- Joined:
Re: Invoke Storyboard on specific DataTemplate Instance
I think I didn't explain well enough how to find the ItemsHost panel.
If you are not able to name the panel yourself because you are using a predefined template for the ItemsControl, then you have to iterate through its children, including all descendants (you don't know how deep in the template's visual tree is the ItemsHost panel):
If you are not able to name the panel yourself because you are using a predefined template for the ItemsControl, then you have to iterate through its children, including all descendants (you don't know how deep in the template's visual tree is the ItemsHost panel):
Code: Select all
Panel* GetItemsHost(FrameworkElement* element)
{
NsSize numChildren = VisualTreeHelper::GetChildrenCount(element);
for (NsSize i = 0; i < numChildren; ++i)
{
FrameworkElement* child = NsDynamicCast<FrameworkElement*>(
VisualTreeHelper::GetChild(element, i));
Panel* panel = NsDynamicCast<Panel*>(child);
if (panel != 0 && panel->GetIsItemsHost())
{
return panel;
}
panel = GetItemsHost(child);
if (panel != 0)
{
return panel;
}
}
return 0;
}
// ... then use that function over your items control
Panel* itemsHost = GetItemsHost(myListBox);
- Nir Hasson
- Posts: 71
- Joined:
- Contact:
Re: Invoke Storyboard on specific DataTemplate Instance
Thank you very much !
It works now
It works now
Who is online
Users browsing this forum: Ahrefs [Bot] and 34 guests