Skip to content

Commit d07a6b6

Browse files
author
Ariel Silahian
committed
Improve MetricTile tooltip rendering and update logic
Refactored MetricTile to remove the hidden TextBox and instead update the tooltip TextBlock directly when the Tooltip property changes or the control loads. Tooltips now support basic HTML formatting (<b>, <i>, <br>) and handle malformed HTML gracefully. The control now listens for DataContext and property changes to keep tooltips up-to-date.
1 parent c22ed46 commit d07a6b6

2 files changed

Lines changed: 86 additions & 33 deletions

File tree

UserControls/MetricTile.xaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
55
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6-
xmlns:local="clr-namespace:VisualHFT.Converters" xmlns:viewmodel="clr-namespace:VisualHFT.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:vmTile}"
6+
xmlns:local="clr-namespace:VisualHFT.Converters"
7+
xmlns:viewmodel="clr-namespace:VisualHFT.ViewModel"
8+
d:DataContext="{d:DesignInstance Type=viewmodel:vmTile}"
79
mc:Ignorable="d"
810
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
911
TextElement.FontWeight="Regular"
@@ -12,9 +14,8 @@
1214
TextOptions.TextRenderingMode="Auto"
1315
Background="{DynamicResource MaterialDesignPaper}"
1416
FontFamily="{StaticResource MaterialDesignFont}"
15-
16-
17-
d:DesignHeight="250" d:DesignWidth="300">
17+
d:DesignHeight="250" d:DesignWidth="300"
18+
Loaded="UserControl_Loaded">
1819
<UserControl.Resources>
1920
<ResourceDictionary>
2021
<ResourceDictionary.MergedDictionaries>
@@ -33,7 +34,6 @@
3334
<Grid.ToolTip>
3435
<TextBlock x:Name="txtToolTip" TextWrapping="Wrap" Width="300" />
3536
</Grid.ToolTip>
36-
<TextBox Visibility="Collapsed" Text="{Binding Tooltip, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" TextChanged="TextBox_TextChanged" />
3737

3838
<Viewbox Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Visibility="{Binding ValueVisibility}">
3939
<TextBlock Text="{Binding Value}" Foreground="{Binding ValueColor}" ToolTip="{Binding ValueTooltip}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="2 0 2 0"/>

UserControls/MetricTile.xaml.cs

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System.Text.RegularExpressions;
2+
using System.Windows;
23
using System.Windows.Controls;
34
using System.Windows.Documents;
45
using System.Xml;
6+
57
namespace VisualHFT.UserControls
68
{
79
/// <summary>
@@ -12,59 +14,110 @@ public partial class MetricTile : UserControl
1214
public MetricTile()
1315
{
1416
InitializeComponent();
17+
18+
// Subscribe to DataContext changes to update tooltip
19+
DataContextChanged += MetricTile_DataContextChanged;
20+
}
21+
22+
private void MetricTile_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
23+
{
24+
if (e.NewValue is VisualHFT.ViewModel.vmTile tile)
25+
{
26+
// Subscribe to property changes
27+
tile.PropertyChanged += Tile_PropertyChanged;
28+
29+
// Update tooltip immediately with current value
30+
UpdateTooltip(tile.Tooltip);
31+
}
32+
33+
if (e.OldValue is VisualHFT.ViewModel.vmTile oldTile)
34+
{
35+
// Unsubscribe from old tile
36+
oldTile.PropertyChanged -= Tile_PropertyChanged;
37+
}
1538
}
1639

17-
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
40+
private void Tile_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
1841
{
19-
TextBox textBox = sender as TextBox;
20-
if (textBox != null)
42+
if (e.PropertyName == nameof(VisualHFT.ViewModel.vmTile.Tooltip))
2143
{
22-
ConvertHtmlToTextBlock(textBox.Text, txtToolTip);
44+
var tile = sender as VisualHFT.ViewModel.vmTile;
45+
UpdateTooltip(tile?.Tooltip);
2346
}
2447
}
48+
49+
private void UserControl_Loaded(object sender, RoutedEventArgs e)
50+
{
51+
// Update tooltip when control loads
52+
if (DataContext is VisualHFT.ViewModel.vmTile tile)
53+
{
54+
UpdateTooltip(tile.Tooltip);
55+
}
56+
}
57+
58+
private void UpdateTooltip(string htmlText)
59+
{
60+
if (string.IsNullOrEmpty(htmlText))
61+
{
62+
txtToolTip.Inlines.Clear();
63+
return;
64+
}
65+
66+
ConvertHtmlToTextBlock(htmlText, txtToolTip);
67+
}
68+
2569
public TextBlock ConvertHtmlToTextBlock(string htmlText, TextBlock textBlock)
2670
{
2771
htmlText = XmlEscapeAmpersands(htmlText);
2872

73+
textBlock.Inlines.Clear(); // Clear existing inlines
2974
textBlock.TextWrapping = System.Windows.TextWrapping.Wrap;
3075
textBlock.Width = 500;
3176

32-
XmlDocument doc = new XmlDocument();
33-
doc.LoadXml("<root>" + htmlText + "</root>");
34-
35-
foreach (XmlNode node in doc.DocumentElement.ChildNodes)
77+
try
3678
{
37-
if (node.NodeType == XmlNodeType.Text)
38-
{
39-
textBlock.Inlines.Add(new Run(node.Value));
40-
}
41-
else if (node.Name == "br")
42-
{
43-
textBlock.Inlines.Add(new LineBreak());
44-
}
45-
else if (node.Name == "b")
46-
{
47-
Run run = new Run(node.InnerText);
48-
run.FontWeight = System.Windows.FontWeights.Bold;
49-
textBlock.Inlines.Add(run);
50-
}
51-
else if (node.Name == "i")
79+
XmlDocument doc = new XmlDocument();
80+
doc.LoadXml("<root>" + htmlText + "</root>");
81+
82+
foreach (XmlNode node in doc.DocumentElement.ChildNodes)
5283
{
53-
Run run = new Run(node.InnerText);
54-
run.FontStyle = System.Windows.FontStyles.Italic;
55-
textBlock.Inlines.Add(run);
84+
if (node.NodeType == XmlNodeType.Text)
85+
{
86+
textBlock.Inlines.Add(new Run(node.Value));
87+
}
88+
else if (node.Name == "br")
89+
{
90+
textBlock.Inlines.Add(new LineBreak());
91+
}
92+
else if (node.Name == "b")
93+
{
94+
Run run = new Run(node.InnerText);
95+
run.FontWeight = System.Windows.FontWeights.Bold;
96+
textBlock.Inlines.Add(run);
97+
}
98+
else if (node.Name == "i")
99+
{
100+
Run run = new Run(node.InnerText);
101+
run.FontStyle = System.Windows.FontStyles.Italic;
102+
textBlock.Inlines.Add(run);
103+
}
104+
// Add more formatting cases as needed
56105
}
57-
// Add more formatting cases as needed
106+
}
107+
catch (XmlException)
108+
{
109+
// If HTML parsing fails, show raw text
110+
textBlock.Inlines.Add(new Run(htmlText));
58111
}
59112

60113
return textBlock;
61114
}
115+
62116
private static string XmlEscapeAmpersands(string s)
63117
{
64118
if (string.IsNullOrEmpty(s)) return s;
65119
// Replace & not starting a valid entity with &amp;
66120
return Regex.Replace(s, "&(?!(?:#\\d+|#x[0-9A-Fa-f]+|[A-Za-z][A-Za-z0-9]*);)", "&amp;");
67121
}
68-
69122
}
70123
}

0 commit comments

Comments
 (0)