Custom Control for a ComboBox with Default Element - wpf

What I want:
I'm trying to create a ComboBox which has a 'Default' element seperated from the rest of the items.
What I have:
So by following the countless threads about grouping the items and overwritting the ItemTemplate I came to this result:
.CS
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ObservableCollection<GroupItem>()
{
new GroupItem() { Name = "Default Item", GroupName = "Default"},
new GroupItem() { Name = "Item 1", GroupName = "Item"},
new GroupItem() { Name = "Item 2", GroupName = "Item"},
new GroupItem() { Name = "Item 3", GroupName = "Item"}
};
}
public class GroupItem
{
public string Name { get; set; }
public string GroupName { get; set; }
}
}
}
XAML
<Window.Resources>
<CollectionViewSource Source="{Binding}" x:Key="GroupedDataCollView">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="GroupName" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<DataTemplate x:Key="GroupHeaderTemplate">
<TextBlock Text="{Binding GroupName}" Margin="10,0,0,0" Foreground="#989791" />
</DataTemplate>
<!--Here, we tell that the URL's description should be displayed as item text.-->
<DataTemplate x:Key="NameTemplate">
<TextBlock Text="{Binding Name}" Margin="10,0,0,0"/>
</DataTemplate>
<Style x:Key="GroupStyleContainerStyle" TargetType="{x:Type GroupItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<StackPanel>
<Separator />
<ItemsPresenter />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Window>
<!-- ... -->
<ComboBox Grid.Row="1" Grid.Column="1"
ItemsSource="{Binding Source={StaticResource GroupedDataCollView}}"
Width="200" Margin="10">
<ComboBox.GroupStyle>
<GroupStyle
ContainerStyle="{StaticResource GroupStyleContainerStyle}"
HeaderTemplate="{StaticResource GroupHeaderTemplate}" />
</ComboBox.GroupStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<!-- ... -->
</Window>
The Problem: Since we use Dictionaries for styling and templates which lie in another project, I can't use this 'solution' because this would require the style to know what kind of items he has to expect (Destroys the isolation of the custom styles and templates). Furthermore it's not really a group that I want to create rather a 'special' item, which is seperated by the others visually.
So I tried to create a custom UserControl to solve the problem so I could use it like this:
<ComboBox ItemsSource="{Binding Items}" DefaultItem="{Binding DefaultItem}" SelectedItem="{Binding SelectedItem}" />
In this CustomControl I would create the necessary grouping and handling hidden from the user. But how can I do this? And how can I overwrite the whole selection behaviour since I don't want to return a Key-Value-Pair (GroupItem) instead of the item the user expects.
So in short: How can I create a CustomControl which provides the necessary functionality shown at the start combined with the simplicity shown above?

Related

Is it possible to have a DataTemplate around another DataTemplate?

Hello everyone and welcome to yet another nested DataTemplate question!
In this one, I'd like to have a DataTemplate like this, written on a ResourceDictionary:
<DataTemplate x:Key="Vector3Template">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<xctk:DoubleUpDown Tag="X" Style="{StaticResource DoubleUpDownStyle}" Value="{Binding X}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<xctk:DoubleUpDown Tag="Y" Style="{StaticResource DoubleUpDownStyle}" Value="{Binding Y}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<xctk:DoubleUpDown Tag="Z" Style="{StaticResource DoubleUpDownStyle}" Value="{Binding Z}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
Being surrounded by a DataTemplate with a border, like the following, also written on a ResourceDictionary (in the future it's gonna have a couple more elements to it):
<DataTemplate x:Key="ComponentTemplate">
<Border Margin="5" BorderThickness="2" BorderBrush="Gray"/>
</DataTemplate>
Why would I want this, you ask? Well, I'm trying to display an ObservableCollection of IComponent named _components and I want all instances to share the same Borders, but with its core being specific to every class type that inherits from IComponent.
In order to display the list with its differents type, I'm using the following code on a UserControl:
<Grid x:Name="LayoutRoot" Background="White">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel>
<ListView x:Name="_componentsList"
ItemsSource="{Binding Components}"
HorizontalContentAlignment="Stretch">
<ListView.Resources>
<DataTemplate DataType="{x:Type models:Transform}">
<ContentControl Content="{StaticResource ComponentTemplate}" ContentTemplate="{StaticResource TransformTemplate}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type models:Vector3}">
<ContentPresenter ContentTemplate="{StaticResource Vector3Template}"/>
</DataTemplate>
</ListView.Resources>
</ListView>
</StackPanel>
</ScrollViewer>
Trying to build this system with Prism 6.3 and with almost no code-behind, every c# code that I have is just for models, so no real logic here so far.
Is this possible? How so? I've started playing with WPF a few days ago and still have a lot to learn.
I believe what you're looking for is to simply use a DataTemplateSelector in which the DataTemplate used is determined by the data. You can find a full tutorial here. Once you've setup your DataTemplateSelector you simply would pass it in as the DataTemplate to your control.
public class PropertyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate DefaultnDataTemplate { get; set; }
public DataTemplate BooleanDataTemplate { get; set; }
public DataTemplate EnumDataTemplate { get; set; }
public override DataTemplate SelectTemplate(object item,
DependencyObject container)
{
DependencyPropertyInfo dpi = item as DependencyPropertyInfo;
if (dpi.PropertyType == typeof(bool))
{
return BooleanDataTemplate;
}
if (dpi.PropertyType.IsEnum)
{
return EnumDataTemplate;
}
return DefaultnDataTemplate;
}
}

How to make a recursive ListView in XAML

My model looks like
public class MyVm
{
public string MyTitle { get; set; }
public List<MyVm> Children { get; set; }
public MyVm()
{
this.Children = new List<MyVm>();
}
}
I want to be able to list through all the children and children's children, which I think is recursive.
The MainWindow code behind is
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
this.Kids = new List<MyVm>();
var m = new MyVm();
m.MyTitle = "Title1";
var m2 = new MyVm();
m2.MyTitle = "Title2";
var m3 = new MyVm();
m3.MyTitle = "Title3";
var m4 = new MyVm();
m4.MyTitle = "Title4";
m.Children.Add(m2);
m2.Children.Add(m3);
m3.Children.Add(m4);
this.Kids.Add(m);
}
public List<MyVm> Kids { get; set; }
and finally the MainWIndow view is
<Grid.Resources>
<Style x:Key="MyStyle" TargetType="ListViewItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<HierarchicalDataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding MyTitle}" />
<ListView ItemsSource="{Binding Children}" ItemContainerStyle="{Binding MyStyle}" />
</StackPanel>
</HierarchicalDataTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<ListView ItemsSource="{Binding Kids}" ItemContainerStyle="{StaticResource MyStyle}" />
As you can see I've tried to re-use the same resource for each 'children' to achieve the recursive bit, but sadly, the only thing I see rendered is a single TextBlock with Title2
For these purposes you would use a HierarchicalDataTemplate (which has its own ItemsSource property that you would bind to Children), i am not sure if a ListBox supports it. If not use a TreeView and change the control templates to remove the indentation and the collapse toggle button if you don't want that.
Fixed it
<Grid.Resources>
<DataTemplate DataType="{x:Type a:MyVm}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding MyTitle}" />
<ListView ItemsSource="{Binding Children}">
<ListView.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding }" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</Grid.Resources>
<ListView ItemsSource="{Binding Kids}" />

WPF Sorting ItemsControl under DataTemplate

I am using ItemsControl under DataTemplate. I want to sort ItemsControl ic using id column.
<DataTemplate x:Key="With">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Text="{Binding Path=fil}" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
<mui:ModernButton IconData="{StaticResource PlayIconData}" Click="FullPlayback" Margin="0,0,6,8" ></mui:ModernButton>
</StackPanel>
<StackPanel DockPanel.Dock="Left" Orientation="Horizontal">
<TextBlock Text="{Binding Path=e1}" Foreground="Red" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
<TextBlock Text="{Binding Path=m1}" Foreground="LightSalmon" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
<TextBlock Text="{Binding Path=n1}" Foreground="Orange" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
<TextBlock Text="{Binding Path=m2}" Foreground="LightGreen" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
<TextBlock Text="{Binding Path=m3}" Foreground="Green" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
<TextBlock Text="{Binding ElementName=H1, Path=Items.Count,Mode=OneWay}" Style="{StaticResource Fixed}" Margin="0,0,6,8" />
</StackPanel>
<ItemsControl Name="ic" DockPanel.Dock="Bottom" ItemsSource="{Binding Path=seg}" ItemsPanel="{StaticResource HSPanel}">
<ControlTemplate TargetType="ItemsControl">
<Border>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
</DockPanel>
</DataTemplate>
i tried below options but sorting is not working.
1.Tried sorting in constructor of the user control like following (code behind)
ic.Items.SortDescriptions.Clear();
ic.Items.SortDescriptions.Add(new SortDescription("id", ListSortDirection.Ascending));
ic.Items.Refresh();
But i am unable to access ic in code behind. Errors says "ic does not exists in current context"
2.Tried CollectionViewSource under ItemsControl in xaml which is also not working.
<ItemsControl x:Name="ic" DockPanel.Dock="Bottom" ItemsSource="{Binding Path=segments}" ItemsPanel="{StaticResource HSPanel}">
<ItemsControl.Resources>
<CollectionViewSource x:Key="segments" Source="{Binding seg}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="id" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</ItemsControl.Resources>
<ItemsControl.Template>
3.Tried CollectionViewSource under ControlTemplate in xaml which is also not working.
<ControlTemplate TargetType="ItemsControl">
<ControlTemplate.Resources>
<CollectionViewSource x:Key="segments" Source="{Binding seg}" >
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="sortId" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</ControlTemplate.Resources>
But i initialised Loaded event of ic and tried to do sorting from there.In this case initially when the page loads, the items are not sorted. But when i move to another user control and come back to this current user control, the items looks sorted out perfectly.
private void ic_Loaded(object sender, RoutedEventArgs e)
{
ItemsControl ic = (ItemsControl)sender;
ic.Items.SortDescriptions.Clear();
ic.Items.SortDescriptions.Add(new SortDescription("id", ListSortDirection.Ascending));
ic.Items.Refresh();
}
You have two options :
1 - Sort your source collection (seg) in View Model.
2 - Use CollectionViewSource (http://msdn.microsoft.com/fr-fr/library/system.windows.data.collectionviewsource.aspx).
Here is a full working exemple:
I have added this code in to an empty WPF window:
public class SomeVM
{
public ObservableCollection<SomeItemVM> Items { get; set; }
public SomeVM()
{
Items = new ObservableCollection<SomeItemVM>();
}
}
public class SomeItemVM
{
public string id { get; set; }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//Create some VM
SomeVM data = new SomeVM();
data.Items.Add(new SomeItemVM() { id = "3" });
data.Items.Add(new SomeItemVM() { id = "4" });
data.Items.Add(new SomeItemVM() { id = "1" });
data.Items.Add(new SomeItemVM() { id = "2" });
this.DataContext = data;
}
}
Then in XAML I add a content control that will hold the VM and a DataTemplate that will describe the way the VM will be displayed:
<Window.Resources>
<DataTemplate x:Key="With">
<DockPanel>
<DockPanel.Resources>
<!-- CollectionViewSource should be declared as a resource of parent container of the ItemsControl.
Otherwise there will be an exception of StaticResourceHolder -->
<CollectionViewSource x:Key="segments" Source="{Binding Items}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="id" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</DockPanel.Resources>
<ItemsControl Name="ic" DockPanel.Dock="Bottom" ItemsSource="{Binding Source={StaticResource segments}}">
<ItemsControl.Template>
<ControlTemplate TargetType="ItemsControl">
<Border>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsPresenter />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding id}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource With}"/>
</Grid>
The resulting ItemsControl will display sorted items.
Finally i solved the sorting problem.
I am binding segments(observablecollection< seg>) to the itemscontrol. Previously In code behind i was generating segments directly like below
segments[0].name="GHI";
segments[0].age=40;
segments[1].name="ABC";
segments[1].age=20;
segments[2].name="DEF";
segments[2].age=30;
Instead of generating segments directly, i created another variable objSegments and generated the values like below.
objSegments[0].name="GHI";
objSegments[0].age=40;
objSegments[1].name="ABC";
objSegments[1].age=20;
objSegments[2].name="DEF";
objSegments[2].age=30;
After generating all the values, sorting is done and assigned to segments using the code below.
ObservableCollection<seg> sortedSegments = new ObservableCollection<seg>(objSegments.OrderBy(c => c.id));
foreach (var objSeg in sortedSegments)
{
segments.Add(objSeg);
}
It worked fine for me.

WPF listbox groupping by substrings

My object has property that stores more strings separated by separator.
I want to display list of such objects in WPF listbox with grouping enabled. What I need is to have groups according to substrings.
Object1: Property = "string1;string2;string3"
Object2: Property = "string2;string3"
I expect listbox to be displayed like that:
string1
Object 1
Object 2
string2
Object 1
string3
Object 1
Object 2
Is that possible?
Thank you for your help.
Create a wrapper class.
class MyGroup
{
public string GroupID;
public object SomeObject;
}
Build your flat list of that wrapper class.
private List<MyGroup> BuildItemsSourceTogether()
{
List<MyGroup>itemsSource = new List<MyGroup>();
foreach(var obj in myListWithObjectsWhichPropertiesAreStringsWhichFuthermoreContainSubstrings)
{
var stringArray = obj.Property123.Split(';');
foreach(var str in stringArray)
{
itemsSource.Add(new MyGroup () { GroupID = str, SomeObject = obj});
}
}
return itemsSource;
}
Tell what property in your wrapper class should be used for grouping.
class Window1
{
public Window1()
{
InitalizeComponents();
var finalData = new ListCollectionView(BuildItemsSourceTogether());
finalData.GroupDescriptions.Add(new PropertyGroupDescription("GroupID"));
this.DataContext = finalData;
}
}
In XAML set the look of your groups and let WPF group that flat list of IDs for you.
I used a DataGrid with columns. You can use a ListBox.
<DataGrid ItemsSource="{Binding}">
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander>
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=ItemCount}"/>
<TextBlock Text="Items"/>
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<DataGridTextColumn Header="header1" Binding="{Binding SomeObject.Property321}" />
<DataGridTextColumn Header="header2" Binding="{Binding SomeObject.Property678}" />
</DataGrid.Columns>
</DataGrid>
Have fun.

Windows Explorer Tooltip in WPF

its not that hard what i want, but i'm pulling my hairs for days!
i just want the same tooltip behaviour like the WIndows Explorer:
overlay a partially hidden tree/list element with the tooltip that displays the full element
i use the following datatemplate in my treeview
<HierarchicalDataTemplate DataType="{x:Type TreeVM:SurveyorTreeViewItemViewModel}" ItemsSource="{Binding Children, Converter={StaticResource surveyorSortableCollectionViewConverter}}">
<StackPanel x:Name="SurveyorStackPanel" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Orientation="Horizontal" Height="20" Width="auto">
... (Textblocks, properties, usercontrol, border,... )
<StackPanel.ToolTip>
<ToolTip Placement="RelativePoint" Padding="0" HasDropShadow="False"
DataContext="{Binding ElementName=SurveyorStackPanel}">
<Rectangle HorizontalAlignment="Left" VerticalAlignment="Center"
Width="{Binding ElementName=SurveyorStackPanel, Path=Width}"
Height="{Binding ElementName=SurveyorStackPanel, Path=Height}">
<Rectangle.Fill>
<VisualBrush AutoLayoutContent="True" AlignmentX="Left"
Visual="{Binding}" Stretch="None"/>
</Rectangle.Fill>
</Rectangle>
</ToolTip>
</StackPanel.ToolTip>
</StackPanel>
</HierarchicalDataTemplate>
As you can see, i'm trying to use Visualbrush. but this doesnt work. it only shows what you see on the screen.
I have tried with static resource and binding on a new stackpanel thats in the tooltip, but that only leaves with a blanc tooltip.
Do i something wrong? do i have to use alternatives?
i'm pretty new in WPF. i know the basics, but binding/resources is kinda new for me
EDIT
here is the static source i tried:
<ToolTip x:Key="reflectingTooltip" DataContext="{Binding Path=PlacementTarget, RelativeSource={x:Static RelativeSource.Self}}" Placement="RelativePoint" Padding="0" HasDropShadow="False">
<Rectangle Width="{Binding ActualWidth}" Height="{Binding Path=ActualHeight}" Margin="0"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle.Fill>
<VisualBrush Visual="{Binding}" Stretch="None" AlignmentX="Left" />
</Rectangle.Fill>
</Rectangle>
</ToolTip>
EDIT 2
Here are a few pics from the situation i have now:
the whole element must be shown when tooltip shows.
before tooltip: http://desmond.imageshack.us/Himg832/scaled.php?server=832&filename=beforedo.png&res=landing
when tooltip is shown: http://desmond.imageshack.us/Himg842/scaled.php?server=842&filename=afterbl.png&res=landing
tooltip has too large height and only shows what screens shows. only problem is to 'fiil in' the hidden text.
VisualBrush renders as a bitmap exactly the same thing you are providing by the 'Visual' property, and it does so without any modification to that thing: it renders them exactly as they are now.
If you want to display something else, you have to provide that something else.. Could you try with something like that: ?
<Window x:Class="UncutTooltip.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Orientation="Horizontal">
<ListBox ItemsSource="{Binding}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Width" Value="250" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<TextBlock Text="{Binding TheText}"
TextTrimming="CharacterEllipsis">
</TextBlock>
<Grid.ToolTip>
<TextBlock Text="{Binding TheText}"
TextTrimming="CharacterEllipsis">
</TextBlock>
</Grid.ToolTip>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Border Background="Red" >
<TextBlock Margin="5" Foreground="WhiteSmoke" FontSize="18"
Text="The end of window:)" TextAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90" />
</TextBlock.LayoutTransform>
</TextBlock>
</Border>
</StackPanel>
</Window>
---
using System.Collections.Generic;
using System.Windows;
namespace UncutTooltip
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new List<Item>
{
new Item { TheText = "its not that hard what i want, but i'm pulling my hairs for days!" },
new Item { TheText = "i just want the same tooltip behaviour like the WIndows Explorer: overlay a partially hidden tree/list element with the tooltip that displays the full element" },
new Item { TheText = "i use the following datatemplate in my treeview" },
new Item { TheText = "As you can see, i'm trying to use Visualbrush. but this doesnt work. it only shows what you see on the screen." },
new Item { TheText = "I have tried with static resource and binding on a new stackpanel thats in the tooltip, but that only leaves with a blanc tooltip." },
new Item { TheText = "Do i something wrong? do i have to use alternatives? i'm pretty new in WPF. i know the basics, but binding/resources is kinda new for me" },
};
}
}
public class Item
{
public string TheText { get; set; }
}
}
Edit:
Now, change the tooltip contents to i.e.:
<Grid.ToolTip>
<ListBox ItemsSource="{Binding TheWholeList}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<!--<Setter Property="Width" Value="250" />-->
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<TextBlock Text="{Binding TheText}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid.ToolTip>
and also change the data definition to:
public class Item
{
public string TheText { get; set; }
public IList<Item> TheWholeList { get; set; }
}
var tmp = new List<Item>
{
.........
};
foreach (var it in tmp)
it.TheWholeList = tmp;
this.DataContext = tmp;
Note that I've commented out the width constraint in the tooltip's listbox, it will present an untruncated list of untruncated elements..
Edit #2:
<StackPanel Orientation="Horizontal">
<ListBox x:Name="listbox" ItemsSource="{DynamicResource blah}"> // <---- HERE
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Width" Value="250" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<TextBlock Text="{Binding TheText}" TextTrimming="CharacterEllipsis" />
<Grid.ToolTip>
<ToolTip DataContext="{DynamicResource blah}"> // <---- HERE
<TextBlock Text="{Binding [2].TheText}" /> // <---- just example of binding to a one specific item
<!-- <ListBox ItemsSource="{Binding}"> another eaxmple: bind to whole list.. -->
</ToolTip>
</Grid.ToolTip>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
public class Item
{
public string TheText { get; set; }
}
public MainWindow()
{
InitializeComponent();
Resources["blah"] = new List<Item> // <---- HERE
{
new Item { TheText = ........
........
In the last example, I've changed the window.DataContext binding, to a binding to a DynamicResource. In the window init, I've also changed the way the data is passed to the window. I've changed the tooltip template to include the Tooltip explicitely, and bound it to the same resource. This way, the inner tooltip's textblock is able to read the 3rd row of the datasource directly - this proves it is bound to the list, not to the Item.
However, this is crappy approach. It will work only with explicit Tooltip, only with Tooltip.DataContext=resource, and probably, it is the only working shape of such approach.. Probably it'd be possible to hack into the tooltip with attached behaviours and search it's parent window and get the bindings to work, but usually, it's not worth.. Could you try binding to the Item's properties like in the second sample?

Resources