I've tried several different solutions to this, but can't land on one that meets all of my needs.
We have an observable collection of objects that each have a status and a name. It's a sort of task-list of running items. To display this list in WPF, we have some code that represents each item as an ellipse with some colors and animations.
The problem is that we want to display the name of the item as a 'popup' both on mouseover, or when the task is in a given state.
Attempt #1
My first attempt implemented this as a Datatemplate (to be used as an ItemTemplate) with an actual WPF Popup. I implemented two datatriggers - one for mouseover and one for task state. I positioned the popup based on my ellipse and everything was great. However, moving the window or switching to a different window left the popup on top of everything.
Attempt #2
Instead of using the popup I used a textbox in a canvas. This works great until the Datatemplate is used in the Listbox. The item host (stackpanel) ends up clipping the string.
Here's example code:
<DataTemplate x:Key="EllipseTemplate">
<Grid Height="40" Width="40">
<Canvas Name="PopupCanvas" HorizontalAlignment="Center" Width="500">
<TextBlock Name="PopupName"
Width="{Binding ElementName=PopupCanvas, Path=ActualWidth}"
Text="{Binding}"
Background="Transparent"
FontSize="16" HorizontalAlignment="Center" TextAlignment="Center" FontWeight="Bold"
Canvas.Top="-25"
Visibility="Collapsed"
/>
</Canvas>
<Ellipse x:Name="Ellipse" Height="25" Width="25" Margin="0"
HorizontalAlignment="Center" VerticalAlignment="Center"
Fill="Green"
RenderTransformOrigin="0.5, 0.5" StrokeThickness="0.5" Stroke="Black">
</Ellipse>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource TemplatedParent}}" Value="True">
<Setter TargetName="PopupName" Property="Visibility" Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<Grid Name="Test" Background="LightGoldenrodYellow" ClipToBounds="False" Margin="50">
<ListBox Name="OverlayTest"
Background="CornflowerBlue"
BorderThickness="0"
VerticalAlignment="Center"
Margin="10"
ClipToBounds="False"
ItemTemplate="{StaticResource EllipseTemplate}">
<sys:String>Very long string that will get clipped</sys:String>
<sys:String>Two</sys:String>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" Margin="10,50,10,50" ClipToBounds="False"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
Attempt #3
I moved my canvas/textbox outside of the datatemplate and create a grid to put it above the listbox of ellipses. This works from a layout perspective, but creates a big mess in terms of checking for mouseover and centering the textbox on the control that's active/hovered.
So that leaves me without an implementation that works the way I want. Anyone have any suggestions?
Ok here I have another idea. I had problem with the ListBox before. Try replacing the ListBox with an ItemsControl.
Attempt #2 sounds like is working fine. You should be able to solve the issue of the clipping using one of these solutions (or all of them):
Set the ClipToBounds property of the ListBox to false
Set the ClipToBounds property of the Stackpanel to false
Related
I am able to zoom using Magnifier (Xceed's control toolkit).
I have multiple controls in Grid that I want to get rid off imageEditor and ListBox controls from Magnifying Glass when it gets zoom.
My code is below.
<Grid>
<wpfMagnifier:MagnifierManager.Magnifier>
<wpfMagnifier:Magnifier x:Name="magnifiyingGlass" Visibility="Hidden"
FrameType="Circle" Radius="240" ZoomFactor=".4" BorderBrush="#9cc63e" BorderThickness="9">
</wpfMagnifier:Magnifier>
</wpfMagnifier:MagnifierManager.Magnifier>
<Image x:Name="cvT" >
</Image>
<imageEditor:UserControl1 x:Name="UserControlID1" Points="{Binding Points}" IsClosedCurve="{Binding IsClosedCurve}" />
<ListBox ItemsSource="{Binding Points}" ItemContainerStyle="{StaticResource PointListBoxItemStyle}" x:Name="ItemsContainer"
PreviewMouseLeftButtonDown="ItemsContainer_PreviewMouseLeftButtonDown" MouseMove="ItemsContainer_MouseMove" PreviewMouseLeftButtonUp="ItemsContainer_PreviewMouseLeftButtonUp">
<ListBox.Template>
<ControlTemplate>
<Canvas IsItemsHost="True"/>
</ControlTemplate>
</ListBox.Template>
</ListBox>
</Grid>
How to implement it?
I have the following listbox in my windows phone 8.1 silverlight application
<ListBox x:Name="ScenarioControl" FontFamily="Segoe WP">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Name="myborder" Margin="0,0,0,0" BorderThickness="0,0,0,3" BorderBrush="Black">
<Grid HorizontalAlignment="Stretch" Margin="0,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Tap="TextBlock_Tap" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding Path=Title, Mode=OneTime}" FontFamily="Segoe WP Semibold" Grid.Column="0" FontSize="23"/>
<Image Tap="Image_Tap" Source="/Images/blogger_small.png" HorizontalAlignment="Right" VerticalAlignment="Center" Grid.Column="1" OpacityMask="Black"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
As you can see TextBlock bound dynamically. I need to change some properties for the last TextBlock element but I cannot find method to get exact element inside the code.
I did search and found that there are solutions with ItemContainerGenerator method but that does not work for me, the following line of code always returns null.
ListBoxItem item = this.ScenarioControl.ItemContainerGenerator.ContainerFromIndex(ScenarioControl.Items.Count - 1) as ListBoxItem;
The most common cause of this problem is that the item in question isn't visible when you make the call to ItemContainerGenerator. Most listboxes, etc. virtualize their contents, meaning that they don't generate UI for elements that would not be visible to the user, so when you go to get the container, you just get null.
This Question + Answer(s) sums this up, and offers a solution to the problem.
Using a converter can help. It's not all declarative, but was what I thought initially.
Change style of last item in ListBox
I have got a ListView wich I added Elements by binding. The ListView looks like:
<ListView
x:Name="ListView"
Height="auto"
Width="350"
ItemsSource="{Binding}"
Padding="0,0,-20,0"
Grid.Row="1"
Grid.Column="0"
Background="#EFEFEF"
ItemContainerStyle="{StaticResource ListViewStyle}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Height="50" VerticalAlignment="Top" Margin="0,0,0,0"
<TextBlock Text="{Binding name} TextWrapping="NoWrap"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
With this basic setup there is already an animation when a element is bonded to the underlying List. Strangely to different animations are used. The first element slides in from the right and all other elements popup. I’m searching for a way to animate all added elements the same way (e.g. slide in from the right). I have been locking into the auto generated (by Blend) ListViewStyle for hours now but couldn't find something. Later I found out that it is possible to add this property inside the style:
<Style x:Key="ListViewStyle" TargetType="ListViewItem">
<Setter Property="Transitions">
<Setter.Value>
<TransitionCollection>
<EntranceThemeTransition FromHorizontalOffset="400" />
<PopupThemeTransition FromHorizontalOffset="400"/>
</TransitionCollection>
</Setter.Value>
</Setter>
...
</Style>
The EntranceThemeTransition and PopupThemeTransition seems to be the right properties because they change the behavior of the animation. But I don't know how to use them or how to disable one. How can I get just one animation (slide in from the right) to the ListView?
This should work:
<ListView
x:Name="lv">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel>
<VirtualizingStackPanel.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition
FromHorizontalOffset="400" />
</TransitionCollection>
</VirtualizingStackPanel.ChildrenTransitions>
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
*Update:
You can also use ListView.ItemContainerTransitions to define these transitions.
I've got following code. Why are my items always clipped after about 70px
<sdk:HierarchicalDataTemplate x:Key="OptionsTemplate">
<CheckBox IsTabStop="False" Content="{Binding EnumValue}" IsChecked="{Binding IsSelected, Mode=TwoWay}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="EnumOptionsTemplate" ItemsSource="{Binding Values}" ItemTemplate="{StaticResource OptionsTemplate}">
<TextBlock Text="{Binding EnumType}"/>
</sdk:HierarchicalDataTemplate>
<sdk:TreeView x:Name="FilterTreeView" ItemsSource="{Binding GeoObjectFilter}" ItemTemplate="{StaticResource EnumOptionsTemplate}">
<sdk:TreeView.Template>
<ControlTemplate TargetType="sdk:TreeView">
<StackPanel Background="Transparent">
<ItemsPresenter x:Name="TreeItems" />
</StackPanel>
</ControlTemplate>
</sdk:TreeView.Template>
</sdk:TreeView>
Thanks in advance!
Ho yes i had same issue when redefining the TreeView Template. By the way, i'm not sure you need to, since StackPanel is the Default Template. I got my (wrappanel) template to work by setting a style for ItemsPanel rather than redifining it. And i had to define some width also. Seems the only way to make the Treeview to scale is to bind the width.
See the answer i made to my question here :
https://stackoverflow.com/a/8802718/856501
Greetings,
I'm looking for a way in Silverlight to have a control which repeats a template for each item bound to it.
I'll try to explain a bit better.
http://img51.imageshack.us/i/naamloosmb.png/
in the screenshot you see a few of the lessons available.
The list contains: "Zumba, Squash, Spinning, Spinning Marathon, Personal Trainer (PT) Sessies" etc
Each item has a description, a picture and a button to go to the page for the corrosponding lesson.
Does anyone know if there is a control available which allows me to achieve this?
If not, how should I start to accomplish this?
Why not use a listbox and an itemtemplate?
Here is a great tutorial: http://backissues.code-magazine.com/article.aspx?quickid=112091&page=1
Basically you can use a Setter to define an item template (remember in Silverlight/WPF an item's content can be any object) with a layout inside.
E.g.
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Height="30" Width="30"
Margin="2"
Fill="{Binding Logo}" />
<Label Content="{Binding Name}"
VerticalAlignment="Center"
FontSize="14" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
Producing: