Reusing a tooltip for several textboxes - wpf

What should I write in the value of the Text property of the tooltip resource so it would show the text of each textblock dynamically ?
<StackPanel x:Name="root">
<StackPanel.Resources>
<ResourceDictionary>
<ToolTip x:Key="tooltiptemplate">
<TextBlock Background="LightBlue" TextTrimming="WordEllipsis" Text="?????"/>
</ToolTip>
</ResourceDictionary>
</StackPanel.Resources>
<TextBlock Text="Mickel" ToolTip="{StaticResource tooltiptemplate}"/>
<TextBlock Text="Kim" ToolTip="{StaticResource tooltiptemplate}"/>
<TextBlock Text="Jenny" ToolTip="{StaticResource tooltiptemplate}"/>
</StackPanel>

{Binding PlacementTarget.Text, RelativeSource={RelativeSource AncestorType={x:Type ToolTip}}}

Related

How to stretch the content of a templated MenuItem using WPF

in my WPF application I have a Menu defined as follows:
<Menu
Grid.Column="1"
MinWidth="50"
MinHeight="50"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent"
Visibility="{Binding Path=ShowSynergies, Converter={StaticResource BoolToVisConverter}}">
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</Menu.ItemsPanel>
<MenuItem
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
BorderBrush="Black"
BorderThickness="1"
ItemsSource="{Binding Path=CurrentlyAvailableSynergies, Source={StaticResource ResourceKey=VM}}">
<MenuItem.Header>
<TextBlock
Margin="5"
FontSize="18"
Text="{Binding Path=ActiveSynergy.Synergy, Source={StaticResource ResourceKey=VM}}"
TextAlignment="Center" />
</MenuItem.Header>
<MenuItem.ToolTip>
<TextBlock Text="{Binding Path=ActiveSynergy.Synergy, Source={StaticResource ResourceKey=VM}}" />
</MenuItem.ToolTip>
<MenuItem.Resources>
<HierarchicalDataTemplate DataType="{x:Type ent:VisualSynergy}" ItemsSource="{Binding Path=AvailableDiameters}">
<TextBlock Text="{Binding SynergyText}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type ent:VisualDiameter}">
<TextBlock
VerticalAlignment="Stretch"
Background="Purple"
Text="{Binding Path=VisualValue}">
<intr:Interaction.Triggers>
<intr:EventTrigger EventName="PreviewMouseLeftButtonDown">
<intr:InvokeCommandAction Command="{Binding Path=SelectSynergyCommand}">
<intr:InvokeCommandAction.CommandParameter>
<MultiBinding Converter="{StaticResource ResourceKey=StdMultiConverter}">
<Binding Path="." />
<Binding Path="." Source="{StaticResource ResourceKey=VM}" />
</MultiBinding>
</intr:InvokeCommandAction.CommandParameter>
</intr:InvokeCommandAction>
</intr:EventTrigger>
</intr:Interaction.Triggers>
</TextBlock>
</DataTemplate>
</MenuItem.Resources>
</MenuItem>
</Menu>
Everything is working as intended, all data is bound properly and updated when it should be updated.
My larges issue is that the final TextBlock (the one related to my VisualDiameter type) doe snot stretch to fill the whole MenuItem available space (see screenshot). I've tried also to redefine styles, but since I am inside the MenuItem resources definitions there is something missing and no stretching happens.
Looking ot other questions my issue seems related to the bizzarre definition of TreeView and MenuItem by Microsoft, but I am not confidend enough to start tinkering with basic templates.
You should define an ItemContainerStyle and bind the Command property of the MenuItem container rather than trying to stretch the TextBlock in the DataTemplate:
<MenuItem
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
BorderBrush="Black"
BorderThickness="1"
ItemsSource="{Binding Path=CurrentlyAvailableSynergies}">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding SelectSynergyCommand}" />
</Style>
</MenuItem.ItemContainerStyle>
<MenuItem.Header>
...

Bind to other element in a stackpanel without name

I'm creating a DataTemplate in WPF, so it won't compile if I use x:Name. This is the relevant part of my code:
<DataTemplate>
<StackPanel>
<Image .../>
<Textbox Width={Binding to image?, Path=ActualWidth} />
</StackPanel>
</DataTemplate>
How can I bind to the Image without the use of name?
You can use RelativeSource:
<DataTemplate>
<StackPanel>
<Image Source="{Binding Photo}"/>
<TextBox Width="{Binding Path=Children[0].ActualWidth, Mode=OneWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel, AncestorLevel=1}}" />
</StackPanel>
</DataTemplate>
You can't directly binding to Image but you can do that with StackPanel and property Children.

Switch datatemplate depending on a selected string value in combobox

Based on a selected string value in the combobox I want to either show red/blue datatempalte inside the grid.
Can this be done without a ContentControl?
<UserControl.Resources >
<DataTemplate x:Key="red">
<TextBox Text="red" />
</DataTemplate>
<DataTemplate x:Key="blue">
<TextBox Text="blue" />
</DataTemplate>
</UserControl.Resources>
<ComboBox ??? />
<Grid>
// Show red or blue datatemplate here
</Grid>
Why not use a ContentControl?
To make this work simply i would put the templates in an array, which the ComboBox then can bind to:
<x:Array x:Key="templates" Type="{x:Type DataTemplate}">
<DataTemplate>
<DataTemplate.Resources>
<sys:String x:Key="DisplayString">Red</sys:String>
</DataTemplate.Resources>
<TextBox Text="red" />
</DataTemplate>
<DataTemplate>
<DataTemplate.Resources>
<sys:String x:Key="DisplayString">Blue</sys:String>
</DataTemplate.Resources>
<TextBox Text="blue" />
</DataTemplate>
</x:Array>
<ComboBox Name="combo" ItemsSource="{StaticResource templates}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Resources[DisplayString]}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Grid>
<ContentControl ContentTemplate="{Binding SelectedItem, ElementName=combo}" />
</Grid>

TreeView with buttons

I have a TreeView where each node has an icon and a descriptive text. But I do not want any node can be selected. Instead, I want that each node act as a button. It run a command when the user press it. But it may not look like a button or hyperlink
This is what I tried so far. The problem is that the text is blue and the text underlined. In addition, sometime the node is selected and therefore blue.
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:ListGroupViewModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Text}" FontWeight="Bold" ></TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type vm:ListNodeViewModel}">
<TextBlock>
<Hyperlink TextDecorations="{x:Null}" Command="{Binding ClickCommand, Mode=OneTime}">
<StackPanel Orientation="Horizontal">
<Image Margin="0,2,2,0" Source="{Binding Icon}" />
<TextBlock Text="{Binding Text}" />
</StackPanel>
</Hyperlink>
</TextBlock>
</DataTemplate>
</TreeView.Resources>
You should override hyperlink style:
<Style x:Key="HyperlinkStyle" TargetType="Hyperlink">
<Setter Property="Foreground"
Value="Black"/>
<Setter Property="TextDecorations"
Value="{x:Null}"/>
</Style>
<DataTemplate DataType="{x:Type vm:ListNodeViewModel}">
<TextBlock>
<Hyperlink Command="{Binding ClickCommand, Mode=OneTime}"
Style="{StaticResource HyperlinkStyle}">
<StackPanel Orientation="Horizontal">
<Image Margin="0,2,2,0" Source="{Binding Icon}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Hyperlink>
</TextBlock>
</DataTemplate>
To hide tree item selection you could override SystemColors.HighlightBrushKey, which tree view uses to highlight items:
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>

WPF : InputBindings on a StackPanel

I want to put a command on a ListBoxItem. The ListBoxItem use a DataTemplate composed of a StackPanel (containing an Image and a TextBlock, both using Binding). I want that the doubleclick on that ListBoxItem fire the command.
I have tried this :
<DataTemplate>
<StackPanel>
<StackPanel.Resources>
<CommonUI:CommandReference x:Key="DoubleClickCommand" Command="{Binding Path=DefaultCommand}" />
</StackPanel.Resources>
<StackPanel.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{StaticResource DoubleClickCommand}" />
</StackPanel.InputBindings>
<Image Source="{Binding Path=Thumbnail, IsAsync=True}" IsHitTestVisible="False"/>
<TextBlock Text="{Binding Path=Name}" IsHitTestVisible="False">
</StackPanel>
</DataTemplate>
I have also tried to put the Command Resources on a StackPanel containing this StackPanel, without any change.
I am certain of my binding because when I put the InputBindings part on the TextBlock, it works.
Thanks
Try handling the event in the ListBox instead of the StackPanel:
<ListBox>
<ListBox.Resources>
<CommonUI:CommandReference x:Key="DoubleClickCommand" Command="{Binding Path=DefaultCommand}" />
</ListBox.Resources>
<ListBox.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{StaticResource DoubleClickCommand}" />
</ListBox.InputBindings>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Path=Thumbnail, IsAsync=True}" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ListBox>
My code finally looks like this :
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<CommonUI:CommandReference x:Key="DoubleClickCommand" Command="{Binding Path=DefaultCommand}" />
</StackPanel.Resources>
<StackPanel.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{StaticResource DoubleClickCommand}" />
</StackPanel.InputBindings>
<Image Source="{Binding Path=Thumbnail, IsAsync=True}" />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
Thanks anyway, Mr Poulin.

Resources