Reputation: 125581
I have a Listbox containing many items. When I hover over an item I need to display a rather 'heavy' popup. I'm pretty sure that loading the popup for each item is a waste of resources so what I'd like to have is only when I hover over the item I modify the template of the ContentControl within the item to include the Popup. This is what I have so far: (a simplified version) (this code can be pasted into Kaxaml)
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ControlTemplate x:Key="WithPopup" TargetType="ContentControl">
<Grid>
<ContentPresenter Content="{TemplateBinding Content}" Name="Target" />
<Popup PlacementTarget="{Binding ElementName=Target}" IsOpen="True" >
<Border BorderBrush="Red" BorderThickness="1" Background="Pink">
<TextBlock Text="I'd like this to behave like a Popup - not a tooltip!" Margin="10" />
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Page.Resources>
<Grid Height="20" Margin="50,50,0,0" Name="ParentGrid">
<ContentControl>
<TextBlock x:Name="TargetControl" Text="Hover over me!" />
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=TargetControl}" Value="True">
<Setter Property="Template" Value="{StaticResource WithPopup}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
</Page>
The problem is that when I try to MouseOver the Popup - it disappears (like a tooltip) because I I'm the mouse is leaving the original ControlTemplate - which causes the template with the Popup to disappear. Any ideas? Edit: I have codebehind available as well to achieve this (even though I'd prefer xaml)
Upvotes: 1
Views: 12503
Reputation: 125581
I have what I think is (at least part of) a solution: Instead of changing the ContentControl's Template via a Trigger, changing the Popup's content with the Trigger seems to work. So instead of loading a complex Popup with a large Visual Tree for each item, I load a simple Popup with no content for each item - and only fill that content when I MouseEnter the ContentControl. Like so:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<DataTemplate x:Key="popupContent" DataType="{x:Type ContentControl}">
<Border BorderBrush="Red" BorderThickness="1" Background="Pink">
<TextBlock Text="This is behaving like a Popup now!" Margin="10" />
</Border>
</DataTemplate>
<ControlTemplate x:Key="WithPopup" TargetType="ContentControl">
<Grid Name="popupGrid">
<TextBlock Text="Hover over me!" />
<Popup IsOpen="True" >
<ContentControl Name="content" />
</Popup>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=popupGrid}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource popupContent}" TargetName="content" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Page.Resources>
<Grid Height="20" Width="100" HorizontalAlignment="Left" Margin="50,50,0,0">
<ContentControl Template="{StaticResource WithPopup}" />
</Grid>
</Page>
I'm not quite sure how to measure how much I would gain performance-wise using this method, but I think it seems to make sense. I'd still like to hear any other better ideas. Thanks.
Upvotes: 4
Reputation: 20471
You need to do things a little differently - try something like this:
<ContentControl Content="hover over me!">
<ContentControl.ContentTemplate>
<DataTemplate>
<Grid>
<TextBlock x:Name="TargetControl" Text="{TemplateBinding Content}" />
<Popup PlacementTarget="{Binding ElementName=Target}" x:Name="popup">
<Border BorderBrush="Red" BorderThickness="1" Background="Pink">
<TextBlock Text="I'd like this to behave like a Popup - not a tooltip!" Margin="10" />
</Border>
</Popup>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=TargetControl}" Value="True">
<Setter TargetName="popup" Property="IsOpen" Value="true" />
</DataTrigger>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=popup}" Value="true">
<Setter TargetName="popup" Property="IsOpen" Value="true" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
Upvotes: 0