C# WPF how to set tooltip size in a tabcontrol - c#

I have a tabcontrol in which each tabITem is rendered a very big font symbol (see image below)
now the tooltip is set to a very big size according to the very big size of the aforementioned tabItem char.
What I'd like is to keep the tabItem symbol very big but being able to resize the tooltip font.
PLUS
I can't understand why the tabheader tooltip is randomly set on all children. I want it on the tabheader itself and not floating everywhere!
--EDIT---
As requested here is a relevant part of my xaml. I only include tab2 which is shorter but there are several tabItems and all behave the same way.
<!-- +++++++++++++ TAB2 ++++++++++++ -->
<TabItem Name="tabItem2" HorizontalAlignment="Center" Height="80" IsSelected="false" FontSize="{StaticResource TAB_FONTSIZE}">
<TabItem.Header>
<StackPanel>
<TextBlock Text=""/> <-------------unicode symbol very big!
<TextBlock Name="tbTab2" Visibility="Hidden" FontSize="{StaticResource BUTTON_FONTSIZE}" />
</StackPanel>
</TabItem.Header>
<TabItem.Background>
<ImageBrush/>
</TabItem.Background>
</TabItem>
while tooltip is set in code-behind
tabItem2.ToolTip = Langs.Word(Langs.eWords.Pallet);
and it gets the HUGE size of the aforementioned unicode char.
Thanx for any help

The problem here is that you set both font size and tooltip directly on the TabItem, and those are then "inherited" by the item's header and content (the font size is also "inherited" by their tooltips). So in order to accomplish what you're asking you need to be more precise when setting those properties, i.e. set them on appropriate controls and not on the TabItem itself. In your case the following should work as expected.
You want to use the large font only for the unicode character, so set the FontSize property only on the control displaying that character:
<TextBlock Text="" FontSize="{StaticResource TAB_FONTSIZE}" />
You want the tooltip to be displayed only for the header, therefore you should set it on the header. You can do that either in XAML:
<TabItem.Header>
<StackPanel ToolTip="My tooltip text">
...
</StackPanel>
</TabItem.Header>
or in code-behind:
var stackPanel = (StackPanel)tabItem2.Header;
stackPanel.ToolTip = "My tooltip text";

Related

Can't get custom fonts to display at runtime - Windows Phone 8.1 MVVM - FontAwesome

I am having trouble with custom fonts in my Windows Phone 8.1 MVVM app.
I am using FontAwesome icons. I have included the FontAwesome font file in my project. When I set a static control such as this, it works perfectly;
<TextBlock x:Name="txtTest" Grid.Row="3" Text="" Foreground="Black" FontSize="20" FontFamily="/Assets/Fonts/FontAwesome.ttf#FontAwesome"/>
However, what I need is for this to work dynamically. I have a Hub control on the main page of the app, with ListViews in each Hub section. These are bound to a collection of custom objects, populated from an API response. When creating the collection of objects, the code looks for a marker in the response and dynamically sets the FontAwesome icon depending on the marker.
Hub Section code:
<HubSection x:Uid="hubApproved" Header="Approved"
DataContext="{Binding MyObjects.Approved}"
d:DataContext="{Binding MyObjects.Approved}"
HeaderTemplate="{ThemeResource HubSectionHeaderTemplate}" >
<DataTemplate>
<ListView
ItemsSource="{Binding}"
ItemTemplate="{ThemeResource ApprovedTemplate}"
IsItemClickEnabled="True"
ItemClick="ListView_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
</ListView>
</DataTemplate>
</HubSection>
And here is the Approved Template which binds to this:
<DataTemplate x:Key="ApprovedTemplate">
<StackPanel Margin="0,0,0,19" Background="{x:Null}" >
<TextBlock FontFamily="/Assets/Fonts/FontAwesome.ttf#FontAwesome" Text="{Binding Icon}" Foreground="Black" />
<TextBlock Text="{Binding SupplierName}" Style="{ThemeResource ListViewItemTripNameTextBlockStyle}" />
<TextBlock Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" Text="{Binding StartDate}"></TextBlock>
</StackPanel>
</DataTemplate>
The Template contains a TextBlock which binds to the Icon property of my object. This is supposed to then display the appropriate FontAwesome icon, but instead just displays the unicode of the icon:
I have tried defining the font family of the Hub control from the code behind in the view, but it has no effect:
Hub.FontFamily = new FontFamily("ms-appx:///Assets/Fonts/FontAwesome.otf#FontAwesome");
Any ideas on how to dynamically get these icons to display...? Thanks
You should be able to do it like this:
FontFamily fontFam = new FontFamily("ms-appx:///Assets/Fonts/FontAwesome.otf#FontAwesome");
and set FontFamily like this:
Hub.FontFamily = fontFam
I solved this with a workaround. The icons in my ListView will only ever be 1 of 5 possible icons. So instead of setting the unicode, I created 5 different textbox objects in the template definition, one for each icon. The unicode is static, so the dynamic aspect is instead the Visibility of each object. I created corresponding XAML Visibility properties on the custom object. After this, the style object is bound to its Visibility property, like so:
<!--Generic (shopping cart icon)-->
<TextBlock FontFamily="/Assets/Fonts/FontAwesome.otf#FontAwesome" Grid.Column="0" Text="" Style="{ThemeResource ListViewItemTripNameTextBlockStyle}"
VerticalAlignment="Center" Visibility="{Binding VisGeneric}" />
Then when I create the object collection from the API response, I set the appropriate visibility property to be Visible, according the the marker in the response.
I'd like a slightly more elegant solution than this, but essentially it works...

WPF max width of TextBlock in C#

I have need to programmatically create a TextBlock inside a WrapPanel. This TextBlock will act like a heading, therefore I don't want anything to appear to right of the TextBlock. Is there a better way to max out the Width of the TextBlock without doing something like;
myTexblock.Width = 1000000;
Thanks
I think a better solution than putting your header in your WrapPanel is to place the header and WrapPanel in a StackPanel
Something similar to this:
<StackPanel>
<TextBlock Text="Some Header Text"
HorizontalAlignment="Stretch" />
<WrapPanel>
<Button Content="Placeholder" />
<Button Content="Also holding a place" />
</WrapPanel>
</StackPanel>
This gives the same visual effect as what you described without the sloppy property setting.

Why does this ComboBox ignore the DataTemplate when SelectedItem is a ContentControl?

In our application we have a screen design feature which is comprised of a custom ScreenDesignPanel and a Property Grid with a ComboBox at the top which points to the selected item on the ScreenDesignPanel. This allows the user to select the UIElement via the ComboBox or via the mouse to set its properties. We achieve this by binding the ItemsSource of the ComboBox to the ScreenDesignPanel's Children collection, then binding their SelectedItems together. This works great.
However, for whatever reason, if the SelectedItem is a ContentControl or a subclass like Button the ItemTemplate specified for the ComboBox is ignored for the 'selected item area' but it is applied when displaying the item in the dropdown list. If the SelectedItem is not a ContentControl, the template is used in both cases.
This also is seemingly specific to the ComboBox. If we use any other selector control: ListBox, ListView, ItemsControl... even third-party ComboBox controls... they all work as expected, properly applying the DataTemplate. ComboBox is doing something internally which no other control is doing.
Note: Below is an over-simplified example for illustrative purposes of the issue only. It is not how we're actually using it as described above.
Also of note: In the DataTemplate for the ComboBox.ItemTemplate, we are only using properties (i.e. Foreground in the example), and are not displaying the DataContext (i.e. the actual ContentControl) itself. This is important because again, the actual control already exists on the ScreenDesignPanel and therefore can't be used for display in the ComboBox's ItemTemplate as it would have two parents which isn't allowed. In other words, it is being used purely as data here.
One last thing... we have a working solution in our app, which was to wrap the Children before binding it to the ComboBox.ItemsSource. However, I'm still curious as to why the ComboBox behaves the way it does which is SPECIFICALLY what I'm asking. (In other words, I'm not looking for other solutions to this design. We already have a working one. I'm looking for clarity on the odd behavior of the ComboBox itself.)
On to the code!
In the first example below, note how the data template is applied to everything in the dropdown, but the selected item area only uses a template if the selected item is not a ContentControl.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="I am the template" Foreground="{Binding Foreground}" />
</DataTemplate>
</ComboBox.ItemTemplate>
<!-- Four 'Data' items for example only -->
<TextBlock Text="I am a Red TextBox" Foreground="Red"/>
<ListBox Foreground="Purple">
<ListBoxItem>I am a Purple ListBox</ListBoxItem>
</ListBox>
<ContentControl Content="I am a Blue ContentControl" Foreground="Blue" />
<Button Content="I am a Button with Green text" Foreground="Green" />
</ComboBox>
This second example shows that it is completely acceptable and fully supported to use a UIElement as the content of a ContentPresenter and still use a DataTemplate (via ContentTemplate) so you can use it in a purely-data role, allowing the template itself to define the visual appearance without displaying the UIElement itself, which is used purely as data here.
<ContentPresenter>
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock Text="I am the ContentTemplate" Foreground="{Binding Foreground}" />
</DataTemplate>
</ContentPresenter.ContentTemplate>
<ContentPresenter.Content>
<Button Content="I am the button" Foreground="Green" />
</ContentPresenter.Content>
</ContentPresenter>
Again, the issue is specific to a ComboBox. I want to find out why the data template isn't applied in that single case, and how to force it to be applied, if possible.
Of note, ComboBox does define SelectionBoxItemTemplate which is separate from the regular ItemTemplate but the rub is that is read-only so you can't set it. We really don't want to re-template the ComboBox as that can mess up proper theming.
Have you tried explicitly setting the DataTemplate to the ContentControl.ContentTemplate property?:
<UserControl.Resources>
<DataTemplate x:Key="DataTemplate">
<TextBlock Text="{Binding Content,
StringFormat='Displayed via template: {0}'}" />
</DataTemplate>
</UserControl.Resources>
...
<ContentControl Content="ContentControl"
ContentTemplate="{StaticResource DataTemplate}" />

Synchronize generated items from ItemsSource

I'm looking for an easy way to synchronize Text sizes (Button Content), which are generated by an ItemsControl.
I'm using the following Xaml code:
<ItemsControl ItemsSource="{Binding UseCases}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding DisplayName}" Width="200" Height="200">
<Button.ContentTemplate>
<DataTemplate>
<Viewbox>
<ContentPresenter Content="{Binding}" />
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I want to make the text on the buttons as big as possible, which already works.
But since the text length is different, the text sizes for each button is also different, which looks odd.
Is there a simple way to tell the Viewbox (or any other way) to take the size of the smallest text and use it for every button?
to limit the size of text just use Padding:
Handling text overflow is the complex part. By some reason (the culprit is - ButtonChrome) the button won't take 'TextBlock.TextTrimmingProperty' attached property, however the AttachedProperty mechanism is designed specifically for the cases like that), leaving you with two options:
Override button's template, lookup for ButtonChrome, get rid of it and replace with something, which has a TextBlock, bind that TextBlock's text to ContentControl.Content.
Manage your text overflow by yourself. Sibscribe for SizeChanged event, get size from the event argument (it mightn't be available anywhere else), get the padding and figure out if text exceeds the available size. Replace the excessive part of it with "..".
The moral - not worth doing.
I'd create uniform quadratic launch buttons and put labels beside them.

How to bind item values in an accordion header template

I'm trying to create a simple header template for an accordion object in silverlight 4.
I've added an image and a TextBlock to the header template of the AccordionItem. I want to hide or show the image dependant on the values entered on the page.
Because i want to bind these values directly to the actual accordion item, I've created a new type 'AccordionItemWithIcons' that simply inherits from AccordionItem but adds a couple of dependancy properties to handle this. I'm only showing a couple of those properties for brevity. :)
So, here's my accordion with my 'AccordionItemWithIcons' control. Note that the property 'CheckIsVisible' is of type 'Visibility'
<Grid x:Name="LayoutRoot">
<Controls:Accordion Height="100">
<my:AccordionItemWithIcons
x:Name="FirstItem"
Content="Content Text"
Header="Header Text"
CheckIsVisible="Collapsed"
EventSummary="Summary Text"
HeaderTemplate="{StaticResource AccordionItemHeaderTemplate1}"/>
</Controls:Accordion>
</Grid>
And here is the header template.
<DataTemplate x:Key="AccordionWithIcons_HeaderTemplate1" >
<Grid >
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<TextBlock Text="{Binding EventSummary}" />
<Image Visibility="{Binding CheckIsVisible}" Source="/Labyrinth;component/cross.png"/>
</StackPanel>
</Grid>
</DataTemplate>
Can anyone explain how I can bind the TextBlock's text and the Image's Visibility to the values set in the underlying AccordionItemWithIcons object? I've spent hours messing about with different DataContext's and sources and cannot seem to get this to work!
I don't know if helps to explain what I'm trying to achieve, but ultimately in the code behind i want to be able to say something like (shown below), to show or hide the icon in the header template.
FirstItem.CheckIsVisible = Visibility.Visible
For this, there exists a VisibilityToBooleanConverter
<BooleanToVisibilityConverter x:Key=”boolVisConverter”/>
[...]
Visibility="{Binding ElementName=anyCheckbox,
Path=IsChecked,
Converter={StaticResource boolVisConverter}}"

Categories