Windows Phone textoutlining - c#

is it possible to outline text in windows phone 8, for example I have red text, but I want the outline to be black?
Should I do this in xaml of C#, and also if possible how? any examples will be much appreciated
thanx

Here you can see how it WAS DONE: http://blog.mrlacey.co.uk/2010/06/silverlight-effects-and-windows-phone-7.html
It's not working anymore. Microsoft removed it, due to performance issues.
The performance hit that applications took from using these effects put too much of a strain on the system and it was decided that if we couldn’t deliver a perfomant feature we would disable until such a time as we could.
The only possibility would be to create 2 TextBlocks and change the FontSize, RenderTransfor, FontWeight,...
<TextBlock Text="{Binding ElementName=BackgroundText,Path=Text}" FontSize="25" Foreground="Red" FontWeight="ExtraBold">
</TextBlock>
<TextBlock Text="Hello" Name="BackgroundText" FontSize="25" Foreground="White" FontWeight="Bold">
<TextBlock.RenderTransform>
<TranslateTransform X="0.5" Y="0" />
</TextBlock.RenderTransform>
</TextBlock>
</TextBlock>

Since two TextBlocks with different FontWieghts won't help you with large text (just longer than simple "Hello") because bolder text will be ahead of thin one, I recommend you to use 4 TextBlocks shifted by 1 upper-left, upper-right etc. and set Opacity = 0.5 to smoothen the outline.
Here an example:
<TextBlock Grid.Row="0" Text="Outlined text" Style="{StaticResource OutlineTb}">
<TextBlock.RenderTransform>
<TranslateTransform X="-1" Y="1" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Grid.Row="0" Text="Outlined text" Style="{StaticResource OutlineTb}">
<TextBlock.RenderTransform>
<TranslateTransform X="-1" Y="-1" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Grid.Row="0" Text="Outlined text" Style="{StaticResource OutlineTb}">
<TextBlock.RenderTransform>
<TranslateTransform X="1" Y="-1" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Grid.Row="0" Text="Outlined text" Style="{StaticResource OutlineTb}">
<TextBlock.RenderTransform>
<TranslateTransform X="1" Y="1" />
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Grid.Row="0"
Text="Outlined text"
FontSize="25"
Foreground="White"
FontWeight="Normal">
</TextBlock>
And style:
<Style TargetType="TextBlock" x:Key="OutlineTb">
<Setter Property="FontSize" Value="25" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="Opacity" Value="0.5" />
</Style>
But keep in mind that it's quite "heavy" solution and still not as good as genuine outline.

Related

StackPanel Collapsed and Visible on Button Click

I am trying to show one collapsed stackpanel on button click, but I'm having problems so I tried reverse my thoughts and I was able to collapse an visible stackpanel. But unfortunately I was unable to implement the behavior I want, show an collapsed stack panel on button click. To the code :D
XAML
<Button x:Name="sentButton" Content="Add Friend" Style="{DynamicResource FlatButtonStyle}" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Style="{DynamicResource stackCollapsed}" Visibility="Collapsed">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource MyTextBox}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Style="{DynamicResource FlatButtonStyle}" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
Styles
<!-- Style Collapsed-->
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="StackPanel.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
Instead of Button use ToggleButton and bind StackPanel.Visibility to ToggleButton.IsChecked property via BooleanToVisibilityConverter converter
<ToggleButton x:Name="sentButton" Content="Add Friend" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Visibility="{Binding ElementName=sentButton, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
where converter is defined as below
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</ResourceDictionary>
</Window.Resources>
The problem is the Visibility property in the <StackPanel> tab takes a higher precedence than anything set in a Style or Trigger, so the Trigger never gets applied. See the Dependency Property Precedence List for more details.
To fix your current solution, move the Visibliity property out of the <StackPanel> tag and into your Style, like this :
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<StackPanel Style="{DynamicResource stackCollapsed}">
...
</StackPanel>
That said, I would personally recommend something like a Toggle Button with the StackPanel.Visibility bound to the ToggleButton.IsChecked, like this answer suggests.
I solved set the Children to null
stackPanel.Children.Clear();
this work if you need to show / hide the panel the first time, it doesn't work if you need to do runtime
Simple as Stackpanel.Visibility = Visibility.Collapsed.

Windows 8.1 scale transform incorrect

I am designing a Windows 8.1 app in C#/XAML. I am trying to replicate the tilt effect found on Windows Phone. I have tried this with both a ScaleTransform and a PointerDownThemeAnimation.
However, the scale effect seems broken in the Y direction. It pushes the UI element down vertically on the page, instead of just scaling it smaller. I have used scale in Windows 8 apps before 8.1 and not had this issue.
Even stranger is in design view it works fine. I have tried setting RenderTransformOrigin to "0.5, 0.5". Here is an example of what happens when I set the text block's scale to 0.5:
What do you think the issue is and how can it be resolved? Thanks
Edit: Here is most of the XAML:
<Grid Height="{Binding PalettePanelHeight}">
<TextBlock Text="Palettes" FontSize="70" Margin="24,22,0,0"/>
<StackPanel Orientation="Horizontal" Name="typePanel" HorizontalAlignment="Right" Margin="0,52,24,0">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="0,0,24,0"/>
<Setter Property="FontWeight" Value="Light"/>
<Setter Property="FontSize" Value="28"/>
</Style>
</StackPanel.Resources>
<TextBlock Text="Newest" Opacity="1" PointerPressed="on_PointerDown" PointerExited="on_PointerUp" PointerReleased="on_PointerUp" Tapped="newest_Tapped" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Text="Most popular" Opacity="0.45" PointerPressed="on_PointerDown" PointerExited="on_PointerUp" PointerReleased="on_PointerUp" Tapped="popular_Tapped" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<ScaleTransform/>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock Text="Highest rated" Opacity="0.45" PointerPressed="on_PointerDown" PointerExited="on_PointerUp" PointerReleased="on_PointerUp" Tapped="rating_Tapped" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<ScaleTransform/>
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
The 'Newest' text block with scale 0.5 is shown in the example image. 'PalettePanelHeight' is just Window.Current.Bounds.Height in code.
If you want to keep the ScaleTransform, use VerticalAlignment to ensure that the text will be on top
<TextBlock VerticalAlignment="Top" Text="Newest" Opacity="1" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5"/>
</TextBlock.RenderTransform>
</TextBlock>
If you want to keep it like other titles, remove the scaleTrandform and make it:-
<TextBlock VerticalAlignment="Top" Text="Newest" Opacity="1" RenderTransformOrigin="0.5,0.5">
</TextBlock>

Mah Apps Tile Animation

I would like to add the Live Tile effect to the tiles on my wpf app layout. I'm using the MahApps.Metro library for the visuals. Here is an example of one of the tiles that I have on the layout -
<Controls:Tile Height="110" Background="#9c6b50" Width="180" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,105,33,0">
<Controls:Tile.Content>
<TextBlock Text="Setup Your Savings Account" TextWrapping="Wrap" Width="121" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Controls:Tile.Content>
</Controls:Tile>
I'd like the end product of the tile to switch between these two texts:
Setup your Savings account
Click here to Setup your savings account
The generally accepted way to do this is by binding the Text property. A binding would look like this:
<TextBlock Text="{Binding Path=TileText}" TextWrapping="Wrap" Width="121" HorizontalAlignment="Center" VerticalAlignment="Center"/>
What this does is bind the value of the TextBlock to a property called TileText on the DataContext of the control. You will need to look into DataContext and binding in WPF to understand this.
Once you have a class with the property:
public string TileText
{
get {...}
set {...}
}
And the class is set as the DataContext of the Tile control you can change the value of the TileText property and it will change the text of the TextBlock. This is a simple example of MVVM design and can be a good first step in understanding smart WPF design practices.
Cheers,
Eric
Try this!
<controls:Tile Height="110" Background="#9c6b50" Width="180" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,105,33,0">
<controls:Tile.Style>
<Style TargetType="controls:Tile">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Setup Your Savings Account" TextWrapping="Wrap" Width="121" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Click here to Setup Your Savings Account" TextWrapping="Wrap" Width="121" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</controls:Tile.Style>
</controls:Tile>

Styling individual cells in a listview

On the internet I found many examples of styling a complete column or complete row in a listview.
I need to be able to dynamically style individual cells in the listview. How can I access the properties of individual items in a row?
If you've got a finite number of properties in your data objects that you want to use to style your items, you can create data templates and styles, and use data triggers to switch between them. I've used something like this to alter the appearance of data objects in a list based on if they are "active/inactive" and to create a collapsed/expanded version of the object based on whether it's selected or not.
You can also use converters (built-in or custom) to get some effects easily. For example, I used a built-in boolean to visibility converter to hide/unhide the combobox/textblock in my TaskSelectedTemplate based on if the object's IsActive member.
<DataTemplate x:Key="TaskSelectedTemplate">
<Grid Margin="4">
...
<Border Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Margin="0 0 4 0"
BorderThickness="0"
CornerRadius="2">
<Border.Background>
<MultiBinding Converter="{StaticResource ActiveToColor}">
<Binding Path="."/>
<Binding Path="IsActive"/>
<Binding Path="IsPaused"/>
</MultiBinding>
</Border.Background>
</Border>
<StackPanel Grid.Row="0" Grid.Column="1"
Orientation="Horizontal"
Margin="0 2">
<ComboBox ItemsSource="{Binding Source={StaticResource TaskTypes}}"
SelectedItem="{Binding Type}"
Text="{Binding Type}"
Visibility="{Binding IsActive, Converter={StaticResource BoolToVis}}"/>
<TextBlock Text="{Binding Type}"
FontWeight="Bold"
Visibility="{Binding IsActive, Converter={StaticResource InvBoolToVis}}"/>
<TextBlock Text=" task"/>
</StackPanel>
...
</Grid>
</DataTemplate>
<DataTemplate x:Key="TaskNotSelectedTemplate">
<Grid Margin="4">
...
<Border Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Margin="0 0 4 0"
BorderThickness="0"
CornerRadius="2">
<Border.Background>
<MultiBinding Converter="{StaticResource ActiveToColor}">
<Binding Path="."/>
<Binding Path="IsActive"/>
<Binding Path="IsPaused"/>
</MultiBinding>
</Border.Background>
</Border>
<TextBlock Grid.Row="0" Grid.Column="1"
Text="{Binding Type}"/>
<TextBlock Grid.Row="0" Grid.Column="2"
TextAlignment="Right">
<Run Text="{Binding Length.TotalMinutes, StringFormat='0', Mode=OneWay}"/>
<Run Text=" min"/>
</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="3"
TextAlignment="Right">
<Run Text="{Binding TimesPerformed, Mode=OneWay}"/>
<Run Text=" tasks"/>
</TextBlock>
</Grid>
</DataTemplate>
<Style x:Key="ContainerStyle" TargetType="{x:Type ListBoxItem}">
<!--this part changes the selected item highlight color-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Name="Border">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border"
Property="Background" Value="#2000BFFF">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--this part causes selected task to expand-->
<Setter Property="ContentTemplate" Value="{StaticResource TaskNotSelectedTemplate}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource TaskSelectedTemplate}"/>
</Trigger>
</Style.Triggers>
</Style>
For more complex scenarios, you might want to look at DataTemplateSelector. I've never used it, but it seems like it might be ideal if you've got a lot of data templates to juggle.
Generally speaking, you shouldn't need this. Assuming you are using GridView, you should be able to use CellTemplate or CellTemplateSelector of your GridViewColumns.
If you really want to access specific cells, I think there is no clean way, you'd be better using DataGrid (from .Net 4 or WPF toolkit for .Net 3.5). With that, you can do something like this:
((TextBlock)datagrid.Columns[1].GetCellContent(m_specificItem)).Background = Brushes.Red

WPF Trigger on TextBlock Inlines

I have a TextBlock that I want to display a user name, and email like this:
Firstname Lastname (Email)
However, I don't want to put the (Email) part in if the user doesn't have an email on file. I would also like to italicize the email. Normally, I would use a TextBlock and add Runs in for the various parts of the text, but I can't find a way to dynamically change a TextBlock's inlines from XAML.
I've tried this:
<TextBlock.Triggers>
<DataTrigger Binding="{Binding Path=HasEmail}" Value="True">
<Setter Property="Inlines" TargetName="contactTagNameEmailTextBlock">
<Setter.Value>
<Run Text="{Binding Path=Firstname}" />
<Run Text="{Binding Path=Lastname}" />
<Run Text="(" />
<Run Text="{Binding Path=Email}" />
<Run Text=")" />
</Setter.Value>
</Setter>
</DataTrigger>
</TextBlock.Triggers>
But VS complains that the value is set more than once (due to the multiple Run's). How can I get around this? Alternatively, it would be really convenient if I could set a binding on a whole FrameworkElement. For example, if I could just put a placeholder in my Grid where I want to put a custom control I construct in code behind on this bound object, that would be the best.
Thanks.
Something like that should work :
<Window.Resources>
<BooleanToVisibility x:Key="visibilityConverter"/>
</Window.Resources>
...
<TextBlock>
<Run Text="{Binding Path=Firstname}" />
<Run Text="{Binding Path=Lastname}" />
<TextBlock Visibility="{Binding HasEmail, Converter={StaticResource visibilityConverter}}">
<Run Text="(" />
<Run Text="{Binding Path=Email}" />
<Run Text=")" />
</TextBlock>
</TextBlock>
Look into Multibinding and StringFormat
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}, {1}">
<Binding Path="LastName" />
<Binding Path="FirstName" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
You should be able to hide the () if email isn't there.
The answer here that says to nest TextBlock elements will cause issues with layout. For instance, the outer TextBlock will no longer properly respect TextTrimming settings.
Here's a better approach which gives you the flexibility of runs set via a trigger* which still allow proper layout.
Note: I added the formatting properties (Foreground, Bold) to show why you would use Runs here instead of a simple multi-binding. Using Runs (or any inlines) allows you to format the text of a TextBlock, but still have it respect layout (i.e. TextTrimming works as expected, etc.)
<ContentControl x:Name="TextBlockPresenter">
<TextBlock TextTrimming="CharacterEllipsis" IsHitTestVisible="False">
<Run Text="{Binding Path=Firstname}" />
<Run Text="{Binding Path=Lastname}" FontWeight="Bold" />
<Run Text="(" Foreground="Gray" />
<Run Text="{Binding Path=Email}" Foreground="Gray" />
<Run Text=")" Foreground="Gray" />
</TextBlock>
</ContentControl>
[SomeTriggerArea]
<DataTrigger Binding="{Binding Path=HasEmail}" Value="False">
<Setter TargetName="TextBlockPresenter" Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<TextBlock TextTrimming="CharacterEllipsis" IsHitTestVisible="False">
<Run Text="{Binding Path=Firstname}" />
<Run Text="{Binding Path=Lastname}" FontWeight="Bold" />
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
[/SomeTriggerArea]
* Technically you aren't setting the runs via a trigger. You're setting an entirely new template which has a TextBox that has the proper runs defined.
It's also a good idea to set IsHitTestVisible to False if you're using Runs like this in a control which you may want to respond to mouse hits, then walk the visual tree (i.e. a TreeView where you listen to a right mouse-down, walk the tree to find the TreeViewItem and set IsSelected to true.) This is because the runs will respond to the mouse, but they aren't a FrameworkElement so when you call VisualTreeHelper.GetParent using e.OriginalSource, you'll get an exception. Simply disabling the TextBlock from participating in the mouse events avoids that.

Categories

Resources