Efficiently display text on image in WPF? - wpf

How to display text on an image, so it should always visible (because the image colors are mixed and unpredictable)?
I thought about two options:
Making the text border in white while the text itself will be black
Having the text displayed negatively to the picture
The 1st option would be preferred since it looks more solid.
Embedding the text is simple:
<Grid>
<Image Source="{Binding ImageLink}" Width="110" />
<TextBlock Text="{Binding Description}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
Update on answer:
Sounds like a great idea except it doesn't work.
I tried your code, and here are the results:
The left image is when I set the Color property to White and ShadowDepth to 10.

I did this and it helps:
<Style x:Key="AnnotationStyle" TargetType="TextBlock">
<Setter Property="Background" Value="#70FFFFFF" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#CCFFFFFF" />
</Trigger>
</Style.Triggers>
</Style>
....
<TextBlock ... Style="{StaticResource AnnotationStyle}"/>
Here is what it looks like:

The best way to make the text more highlighted or contrasted is by using any effect, particularly the shader effects.
Microsoft is also make bitmap effect obsoleted since .NET 3.5 SP1, therefore your best bet is using any shader effect or create your own.
For example (from Karl Shifflett), you can use DropShadowEffect to "outline" your text but set the ShadowDepth to 0:
<Grid>
<Image Source="{Binding ImageLink}" Width="110" />
<TextBlock Text="{Binding Description}"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock.Effect>
<DropShadowEffect ShadowDepth="0" Color="Blue" BlurRadius="10" />
</TextBlock.Effect>
</TextBlock>
</Grid>
For more sample, you can google WPF effects.
UPDATE: You can also turn off antialiasing on text by using attached property of TextOptions.TextRenderingMode and set it to "Aliased", or you can also use TextOptions.TextFormattingMode and set to "Display".
Try and compare this and see if it will fit your needs:
<StackPanel>
<TextBlock>
Hello World ... Ideal text formatting
</TextBlock>
<TextBlock TextOptions.TextFormattingMode="Display">
Hello World ... Display text formatting
</TextBlock>
</StackPanel>
Hope this helps.

Related

WPF Textblock Tooltip does not wrap

I am trying to create a tooltip that wraps automatically (and also has an advanced mode that takes normal content, but that's later). Anyway, I'm setting the content as a string and making the content just a textblock with wrapping. However I can't figure out why this isn't working. Here is the style I'm working on:
<Style x:Key="StHelpLinkBase" TargetType="{x:Type graphicElements:MyHelpLink}">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Background" Value="{StaticResource BrHelpLinkBackground}" />
<Setter Property="Width" Value="12" />
<Setter Property="Height" Value="12" />
<Setter Property="Margin" Value="5" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type graphicElements:MyHelpLink}">
<Grid x:Name="templateRoot">
<Image Source="Images/Icon_16_Help.png" Stretch="UniformToFill" MaxHeight="16" MaxWidth="16"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
x:Name="PART_Image">
<Image.ToolTip>
<ToolTip Background="{TemplateBinding Background}" BorderThickness="0"
DataContext="{Binding DataContext, ElementName=PART_Image}"
TextElement.Foreground="{TemplateBinding Foreground}"
ContentTemplate="{StaticResource DtTooltipAdvanced}"
MaxWidth="150"
x:Name="PART_Tooltip">
<ContentPresenter />
</ToolTip>
</Image.ToolTip>
</Image>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here is the basic template referenced:
<DataTemplate x:Key="DtTooltipBasic">
<Grid>
<TextBlock Text="{Binding Content, RelativeSource={RelativeSource AncestorType=ToolTip}}"
TextWrapping="Wrap"
Foreground="White"
Margin="15"
FontFamily="Resources/#Artifakt Element"
FontSize="9pt" />
</Grid>
</DataTemplate>
And here is the usage (MyHelpLink inherits from ContentControl):
<graphicElements:MyHelpLink Content="This is some help text that is long and is just set as straight string in content but it should wrap I hope." />
I've tried setting the MaxWidth on the tooltip as I have it now, I've tried setting it on the Grid that is in the DataTemplate, and I've tried setting it on the textblock itself and all just cut off the text. I also tried setting the Width property of the textblock directly and same thing...
So why doesn't this wrap?
Ok well I still don't know why this didn't work but I ended up with another solution. Through some experimenting I found that if I put the textblock directly inside the control template instead of a data template it worked and wrapped correctly. However in order to switch it I couldn't use it that way.
So what I did was make two control templates; one with a wrapping textblock for generic content and one with ContentPresenter for non-string content. I then made the style with a trigger on the content type (I made a custom readonly dependency property in my class denoting to trigger the change if the content is anything except a string). The trigger changes the template from the wrapping textblock to the content presenter depending on the type of content set.
If anyone knows why it doesn't work inside a DataTemplate I would love to know and will mark as the answer...

In multiple Y axis graph, the axis shift issue in wpf

I have chart control,depends upon the selection i have to plot a graph,here is screen shot
First case i have selected, 2 inputs and second case given 1 input. as above images it shifts axis.If i refresh it will be the proper position.
<chartingToolkit:Chart Name="lineChart" BorderThickness="0" Padding="0"
Grid.IsSharedSizeScope="True" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<chartingToolkit:Chart.LegendStyle>
<Style TargetType="Control">
<Setter Property="Template" Value="{x:Null}"/>
</Style>
</chartingToolkit:Chart.LegendStyle>
<chartingToolkit:Chart.Axes>
<chartingToolkit:LinearAxis Orientation="X" Minimum="0" Maximum="{Binding MaxX}" Title="Time (Minutes)" />
</chartingToolkit:Chart.Axes>
<chartingToolkit:LineSeries Title="Oxygen" DependentValuePath="Value" IndependentValuePath="Key" Visibility="{Binding O2.GraphVisibility}"
ItemsSource="{Binding O2.TGraph,UpdateSourceTrigger=PropertyChanged}" IsSelectionEnabled="True" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Padding="0" >
<chartingToolkit:LineSeries.DataPointStyle>
<Style TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="{StaticResource graphO2}"/>
</Style>
</chartingToolkit:LineSeries.DataPointStyle>
<chartingToolkit:LineSeries.DependentRangeAxis>
<chartingToolkit:LinearAxis Title="{Binding O2.YTitle}" Foreground="{StaticResource graphO2}" Visibility="{Binding O2.YVisibility}" Maximum="{Binding O2.MaxY}" Orientation="Y" Location="{Binding O2.YLocation}" />
</chartingToolkit:LineSeries.DependentRangeAxis>
</chartingToolkit:LineSeries>
</chartingToolkit:Chart>
Using WPF Toolkit Data Visualization for graph.Please help me solve this issue.Coding side using MVVM architecuture.
It seems that chart doesn't refreshe in proper way, when you change input or modify dependency properties.
At least in LightningChart Visualization component, you can disable chart rendering - modify properties - continue rendering. You can easily prevent such bugs.
Try that and see the result. It has free demoapp with examples and available code. Can help you.

How to write a style for HyperlinkButton Shadow effect in Silverlight

I have a styled HyperlinkButton as per custom need as follow:
<HyperlinkButton Tag="Transactions/HomeWorkPage"
Background="#E9E9EB" Foreground="Black">
<HyperlinkButton.Effect>
<DropShadowEffect Direction="270" Opacity="0.35" ShadowDepth="3"/>
</HyperlinkButton.Effect>
<StackPanel Orientation="Horizontal">
<Image Source="/SchoolMgmt;component/Assets/Images/R_Homework.png"
Margin="10,0,1,0"/>
<telerik:Label Content="Home Work" CharacterSpacing="25"
telerik:StyleManager.Theme="{Binding SelectedTheme,Mode=TwoWay}"
FontSize="12" FontFamily="Arial Rounded MT" Margin="3"/>
</StackPanel>
</HyperlinkButton>
Now with satisfy with the result I started to write a style resource for this so that I can use wherever I want.
This is I am able to write:
<Style x:Name="QuickLinkStyle" TargetType="HyperlinkButton">
<Setter Property="Background" Value="#E9E9EB"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
I am not able to convert following into style
<HyperlinkButton.Effect>
<DropShadowEffect Direction="270" Opacity="0.35" ShadowDepth="3"/>
</HyperlinkButton.Effect>
I am not a designer and not using expression blend for writing a style. I tried to googled it. But all I able to find out is DataTemplate , VisualStates etc. Its very confusing.
So this is not working?
<Style x:Name="QuickLinkStyle" TargetType="HyperlinkButton">
...
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect .../>
</Setter.Value>
</Setter>
</Style>

TextBlock with vertical scrollbar only

I have a TextBlock which may contain a long text so I want to add a vertical scroll bar to it. My initial attempt was to wrap a ScrollViewer around it. That works but the problem is that when I zoom in, the width is zoomed also. I tried disabling the horizontal scroll bar like this:
<ScrollViewer IsTabStop="True" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
But it didn't solve the problem. I also tried binding the width:
Width="{Binding ElementName=Scroller, Path=ViewportWidth}"
It didn't help either.
So, my question is, how can I add vertical scrollbar to it but have a fixed width and wrapped text for the TextBlock inside? Here's my full code:
<ScrollViewer Grid.Row="1" IsTabStop="True" VerticalScrollBarVisibility="Auto">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" TextWrapping="Wrap" TextAlignment="Center"/>
</ScrollViewer>
There are two parts to this answer... the first is to simply use a TextBox:
<TextBox ScrollViewer.VerticalScrollBarVisibility="Visible" Text="Something really
really really really really really really really really long"
Style="{StaticResource TextBlockStyle}" />
The second part is to simply Style the TextBox so that it looks like a TextBlock:
<Style x:Key="TextBlockStyle" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="IsReadOnly" Value="True" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="TextWrapping" Value="Wrap" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
Feel free to remove any of these properties if they do not suit your situation.
<TextBox HorizontalAlignment="Center"
VerticalAlignment="Top"
TextWrapping="Wrap"
TextAlignment="Center"
VerticalScrollBarVisibility="Auto" Width="300" Style="{StaticResource TextBlockStyle}"/>
You don't need a ScrollViewer wrapped in the TextBox, the TextBox control has its own ScrollViewer. And you need to define the width of the TextBox so that the scrollbar will know its fixed width and will wrap the text.
Then, you have to style the TextBox to look like a TextBlock
A good reason why this ScrollViewer won't work according to to Ifeanyi Echeruo from Microsoft, from MSDN
ScrollViewer first asks its content how large it would like to be in
the absence of constraints, if the content requires more space than
the Viewer has then its time to kick in some ScrollBars
In the absence of constraints TextBlock will always opt to return a
size where all text fits on a single line.
A ScrollViewer with ScrollBars will never get a TextBlock to wrap.
However you may be able to come up with a Measure\Arrange combination
for a panel of your own that is almost like ScrollViewer but I cant
think of any logic that can satify both constraints without explicit
knowlege of the behaviour of said children

WPF Charting: how to collapse datapoint dots in lineseries

I have multiple line series in a chart. Chart lines are drawn first and then dots follow the lines. It's annoying and the size of big dots makes large datasets simply useless.
Currently I am doing this for each lineseries...
<chartingToolkit:LineSeries
Title="Socket 2"
Name="LineSocket2"
LegendItemStyle ="{StaticResource LegendItemStyle}"
IndependentValueBinding="{Binding timestamp}"
DependentValueBinding="{Binding wattage}"
ToolTip="Socket 2">
<chartingToolkit:LineSeries.DataPointStyle>
<Style TargetType="{x:Type chartingToolkit:LineDataPoint}">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
</chartingToolkit:LineSeries.DataPointStyle>
</chartingToolkit:LineSeries>
But it doesn't do what I want.
How can it be done?
If it helps anyone, the following works for me:
<chartingToolkit:Chart DataContext="1,10 2,20 3,30 4,40" HorizontalAlignment="Stretch" Margin="-1,14,0,0" Name="chart1" Title="Chart Title" VerticalAlignment="Stretch" Width="806" Height="Auto">
<chartingToolkit:LineSeries Name="Series1" DependentValuePath="X" IndependentValuePath="Y" ItemsSource="{Binding}">
<chartingToolkit:LineSeries.DataPointStyle>
<Style TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Opacity" Value="0" />
<Setter Property="Background" Value="Blue" />
</Style>
</chartingToolkit:LineSeries.DataPointStyle>
</chartingToolkit:LineSeries>
</chartingToolkit:Chart>
The charting toolkit is actually a derivative of the Charting in the Silverlight toolkit.
Hence the answer to the question removing-collapsing-datapoints-in-a-lineseries may work for you.

Resources