TreeViewItem Tooltip Binding Not Working - wpf

I have a treeview. It's bound to an ObservableCollection called Nodes. The bound data on the tool tips is not showing:
<controls:TreeViewEx BorderThickness="0"
ItemsSource="{Binding Nodes}"
SelectedItemEx="{Binding SelectedTreeNode, Mode=TwoWay}">
<controls:TreeViewEx.ToolTip>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Row="0"
Grid.Column="0"
Source="/FMG.UI.WPF;component/Media/Images/job_128.png"
Height="16"
Width="16"/>
<TextBox Grid.Row="0"
Grid.Column="1"
Text="Job: "
FontWeight="Bold"/>
<TextBox Grid.Row="0"
Grid.Column="2"
Text="{Binding ToolTipHeader}"/>
<Border Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Height="2"
BorderBrush="Gray"/>
<TextBox Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="3"
Text="{Binding ToolTipDetails}"/>
</Grid>
</controls:TreeViewEx.ToolTip>
</controls:TreeViewEx>
The tooltip pops up, but the ToolTipHeader and and ToolTipDetails are blank. The Output window says it can't find them on the view model. How do I make the binding look on the Node, not the view model?

You probably want to move the code; use the TreeView.ItemContainerStyle and add a Setter for the ToolTip, this will set a node-level tool-tip.
e.g.
<controls:TreeViewEx.ItemContainerStyle>
<Style TargetType="controls:TreeViewItemEx"> <!-- Guessing at item type name here -->
<Setter Property="Tooltip">
<Setter.Value>
<!-- Move your tooltip here -->
</Setter.Value>
</Setter>
</Style>
</controls:TreeViewEx.ItemContainerStyle>
Of course the DataContext for all the bindings in the tooltip will be the current item, if you want the context of the tree-view specify a RelativeSource that finds it (also prepend "DataContext" on the Path, otherwise you bind to properties directly on the tree-view).

Related

Odd WPF Grid Behavior Affected by TextBox Text

I can't figure out why the contents of my TextBox is affecting my grid column widths. I have setup a grid with 3 columns with widths defined as 50, *, 50, as shown below
Now, when in use, the center column will grow/shrink as the text in the TextBox changes, see the 2 examples below. The actual TextBox is not changing size, so I can't understand why in the world the grid is changing. The Grid is inside of a Border inside a UserControl. The UserControl is used as a DataTemplate in a ListBox.
Edit: I've discovered that this issue is related to the UserControl being in a ListBox, see example image below (UserControl in ListBox (circled in red) vs. UserControl Placed on Form (circed in blue). The grid behaves as expected when the UserControl is placed directly on the form. Code for the form is given below.
UserControl XAML:
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Name:" Margin="2" />
<TextBox Grid.Column="1" Margin="2" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Grid.ColumnSpan="2" />
<TextBlock Text="Shift:" Grid.Row="1" Margin="2" />
<TextBox Grid.Column="1" Grid.Row="1" Margin="2" Text="{Binding TimeShift, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, FallbackValue=0}" HorizontalContentAlignment="Right" />
<TextBlock Text="s" Grid.Row="1" Grid.Column="2" Margin="2" />
</Grid>
Window/Form XAML:
<Window x:Class="CrashSimOffice.FileImport"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CrashSimOffice"
Title="File Import" Height="350" Width="450" Background="White" Icon="/CrashSimOffice;component/Images/16/page-white-save.png">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="75"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="75"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Content="Add" Margin="2" Command="{Binding AddFileCommand}" />
<Button Content="Remove" Grid.Column="1" Margin="2" Command="{Binding RemoveFileCommand}" />
<ListBox HorizontalContentAlignment="Stretch" Grid.ColumnSpan="4" Margin="2" Grid.Row="1" ItemsSource="{Binding Files}" SelectedItem="{Binding CurrentFile}" ScrollViewer.CanContentScroll="False" Background="WhiteSmoke">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:FileViewModel}">
<local:FileView DataContext="{Binding}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Done" Grid.Column="3" Margin="2" Grid.Row="2" Click="Button_Click" />
<local:FileView Grid.Row="3" Grid.ColumnSpan="4" />
</Grid>
OK, I figured it out, Bruno V you got me thinking it must have something to do with the ListBox. I needed to add this to my ListBox:
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Not sure why that works, but it does.

How to add new elements to the base Grid from an inherited DataTemplate?

I have two objects: Bicycle and BicycleFullSuspension, which inherits Bicycle and contains additional properties (strings and decimals). I managed to make a functioning DataTemplateSelector that will choose either my LbxItemTemplateBicycle DataTemplate or my LbxItemTemplateFullSuspension DataTemplate, depending on to which class the object in an ObservableCollection belongs. Both of these templates are bound to the parent template ListBoxItemTemplate.
I am trying to display information about each object in a ListBox, and each of the inheriting templates should add a few more fields to the grid in the parent DataTemplate. My problem is that I cannot figure out how to add WPF elements to the grid in ListBoxItemTemplate from one of the inherited templates. I cannot assign a key to the grid in the template, so I am not sure how to specify that additional TextBlocks should end up in the same grid that is in the parent template. (Right now, additional TextBlocks are stacked on top of the parent grid.)
<DataTemplate x:Key="ListBoxItemTemplate">
<Border Name="LbxItemTemplate" BorderBrush="DarkRed" BorderThickness="2" Padding="5" Margin="5">
<Grid>
<Grid.RowDefinitions>
...
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
...
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Bike Year:" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding BikeYear}" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Bike Color: "/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding BikeColor}"/>
...
</Grid>
</Border>
</DataTemplate>
<DataTemplate x:Key="LbxItemTemplateFullSuspension" DataType="{x:Type app:BicycleFullSuspension}">
<Grid>
<ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource ListBoxItemTemplate}" />
<TextBlock Grid.Row="6" Grid.Column="0" Text="Shock Travel"/>
<TextBlock Grid.Row="6" Grid.Column="1" Text="{Binding ShockTravel}"/>
</Grid>
</DataTemplate>
I found these links helpful for getting to this point:
http://dariosantarelli.wordpress.com/2011/07/28/wpf-inheritance-and-datatemplates/
http://zamjad.wordpress.com/2009/12/31/applying-data-template-conditionally/
Is there a way to use data-template inheritance in WPF?
Edit:
I'm not sure why I didn't think to put the Border on the template inheriting the base, but by nesting a StackPanel inside of the Border in the inheriting template (StackPanel contains the ContentPresenter with the base template content along with the Grid that has the added information), everything lines up very nicely:
Working solution, using input from XAMeLi:
<DataTemplate x:Key="ListBoxItemTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
...
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" SharedSizeGroup="LabelColumnGroup" />
<ColumnDefinition Width="150" SharedSizeGroup="LabelColumnGroup" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Bike Year:" />
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding BikeYear}" />
...
</Grid>
</DataTemplate>
<DataTemplate x:Key="LbxItemTemplateFullSuspension" DataType="{x:Type app:BicycleFullSuspension}" >
<Border BorderBrush="DarkRed" BorderThickness="2" Padding="5" Margin="5" Grid.IsSharedSizeScope="True" Width="500">
<StackPanel>
<ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource ListBoxItemTemplate}" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
...
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelColumnGroup" />
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelColumnGroup" />
</Grid.ColumnDefinitions>
...
<TextBlock Grid.Row="7" Grid.Column="0" Text="Shock Type: "/>
<TextBlock Grid.Row="7" Grid.Column="1" Text="{Binding ShockType}"/>
...
</Grid>
</StackPanel>
</Border>
</DataTemplate>
You cannot add UIElemets to a data template, but you can layout the bigger template to look like it has added text to the base template.
Basically, you are on the right path, only the layout of the big template is corrupt. (Too bad you omitted the structure of your rows and columns)
Try this:
<DataTemplate x:Key="ListBoxItemTemplate">
<Border Name="LbxItemTemplate" BorderBrush="DarkRed" BorderThickness="2" Padding="5" Margin="5">
<Grid>
<Grid.RowDefinitions>
...
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
SharedSizeGroup="LabelGroupColumn"/>
...
</Grid.ColumnDefinitions>
....
</Border>
</DataTemplate>
<DataTemplate x:Key="LbxItemTemplateFullSuspension">
<Grid Grid.IsSharedSizeScope="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/><!--This will hold the default template-->
<!--From here define the same structure as in the default template, if you have rows for margins and such-->
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
SharedSizeGroup="LabelGroupColumn"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource ListBoxItemTemplate}" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Shock Travel"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding ShockTravel}"/>
</Grid>
</DataTemplate>
It seems that your grids have Label-Value structures and you want all the values to start from the same vertical line (this is very good from UX point of view). Notice the SharedSizeGroup setters on column definitions and the Grid.IsSharedSizeScope="True" on a mutual parent. This will keep the width of the label column to be synchronized among the grids.

Telerik Silverlight RadPanelBar Hierarchical Data Template

I need to display the following layout with a telerik PanelBar.
With the code below I was able to achieve everything except the 92% stuff in each panel.
XAML:
<UserControl.Resources>
<DataTemplate x:Key="PanelBarItemTemplate">
<Grid x:Name="grdCategory" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60*"></ColumnDefinition>
<ColumnDefinition Width="40*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid x:Name="grdSubCategory" Grid.Column="0" Style="{StaticResource CategoryLeftStyle}" >
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*"></ColumnDefinition>
<ColumnDefinition Width="25*"></ColumnDefinition>
<ColumnDefinition Width="25*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding CategoryTitle}" Grid.Row="0" Grid.Column="0"/>
<HyperlinkButton Grid.Row="0" Grid.Column="1" Style="{StaticResource DetailLinkStyle}" Content="Details" Click="Home_Click"></HyperlinkButton>
<TextBlock Text="{Binding Score}" Grid.Row="0" Grid.Column="2"/>
</Grid>
<TextBlock Text="92%" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" FontSize="32" FontWeight="Bold"/>
</Grid>
</DataTemplate>
<telerik:HierarchicalDataTemplate x:Key="PanelBarHeaderTemplate"
ItemsSource="{Binding SubReports}"
ItemTemplate="{StaticResource PanelBarItemTemplate}">
<TextBlock Text="{Binding CategoryTitle}" />
</telerik:HierarchicalDataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<telerik:RadPanelBar x:Name="radPanelBar"
ItemTemplate="{StaticResource PanelBarHeaderTemplate}"
IsSingleExpandPath="False" >
</telerik:RadPanelBar>
</Grid>
in the xaml.cs file I provided the ItemsSource.
Can somebody help me out?
All that code works perfectly well for the individual items, but to place the 92% relative to those items (somewhat outside of the sub-items) you would need to also modify the ItemContainerStyle of RadPanelBar. Easiest way is to extract it in Blend, then look for the section under PanelBarItemTopLevelTemplate named ItemsContainer. This is a somewhat crude version, but I made a public property on my item called CalcInt that calculates the sum of a property on the SubReport items so it can be bound from the base item level. My modified code looks like so:
<Grid x:Name="ItemsContainer" Grid.Row="1" Visibility="Collapsed">
<telerik:LayoutTransformControl x:Name="transformationRoot">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ItemsPresenter/>
<TextBlock Text="{Binding CalcInt}" FontSize="48" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</telerik:LayoutTransformControl>
</Grid>
I basically changed it from just containing an ItemsPresenter to a grid with some layout to display my extra-large TextBlock.
If you need a sample of the code or have any other questions feel free to hit me up on Twitter - #EvanHutnick.
Cheers!
-Evan
Hi I think you need to define a converter : IValueConverter and bind to the Label so you can calculate the percentual.
Mario

WPF combobox items list/context menu rendered behind parent

If the ItemSource property of a combo box has been set, why could clicking on the drop down botton of a combobox not display the list of available items? This may be related but within the same control, any context menu is displayed behind the user control:
The XAML for this control is as follows:
<Border Name="Border" Padding="5">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ScrollViewer.Resources>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="Padding" Value="8,0,0,0"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</ScrollViewer.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Margin="5,4,0,4" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition SharedSizeGroup="labelColumn1" />
<ColumnDefinition SharedSizeGroup="labelColumn2" />
<ColumnDefinition SharedSizeGroup="dataEntryColumn" />
<ColumnDefinition Width="30"/>
<ColumnDefinition SharedSizeGroup="labelColumn2"/>
<ColumnDefinition SharedSizeGroup="dataEntryColumn" />
<ColumnDefinition MaxWidth="0" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MinHeight="23" />
<RowDefinition MinHeight="23" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Geometry Type" VerticalAlignment="Center" Grid.Column="1" Grid.Row="0"/>
<ComboBox Grid.Column="3" Margin="6,1,0,1" Grid.Row="0" Width="150"
Name="cmboGeometryTypes"
SelectedItem="{Binding GeometryType, Mode=TwoWay}"
HorizontalAlignment="Left"
DisplayMemberPath="Name"
Grid.ColumnSpan="1"
/>
<TextBlock Text="Symbol Type"
Grid.Column="1" Grid.Row="1" VerticalAlignment="Center"/>
<ComboBox
Name="cmboSymbolEditors"
SelectedItem="{Binding SymbolEditorViewModel, Mode=TwoWay}"
HorizontalAlignment="Left"
DisplayMemberPath="Alias"
Width="150"
Grid.Column="3"
Margin="6,1,0,1"
Grid.Row="1"
Grid.ColumnSpan="1" />
</Grid>
<Label Padding="10,0,0,0" Margin="10,0,0,3" Style="{StaticResource fadingLabelSeperatorStlye}" Grid.Row="1">
Editor
</Label>
<local:SymbologyEditorControl x:Name="editor" Grid.Row="2"/>
</Grid>
</ScrollViewer>
</Border>
and the effect I am observing is illustrated below
How do I fix this?
There was a common WPF bug that caused this behavior of any Popup type UI displaying in back instead of topmost so that may be what you're seeing. I haven't seen the issue in a while but I'm not sure if it was fixed or not. It's related to bad video drivers so you might see it only on certain machines and not all the time.
There was a hotfix available from MS support but it might be easier to just switch your application to use software rendering instead.

Not able to refer a control in code behind in VS 2008 with WPF

I don't know why but for some reason I am not able to refer to my tbText control in my code behind file. Here is the XAML part:
<ComboBox.ItemTemplate>
<DataTemplate>
<ItemsControl x:Name="ic">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
</Grid>
**<TextBlock x:Name="tbText" Grid.Column="0" Grid.Row="0" Margin="10" />**
<Image Grid.Column="1" Margin="10" Grid.Row="0" Width="100" Height="100" Stretch="Fill">
</Image>
</ItemsControl>
</DataTemplate>
</ComboBox.ItemTemplate>
I cannot refer to the "tbText" control.
You can't refer to it because it is inside an Items control.
You'd have to search the ItemsControl children in order to find the textbox.
See Finding control within wpf items control for ways to do this.

Resources