Extend Prism to make use of a stackpanel with this simple solution:
You can use the same technique with a gird or other container control, simply register your adapter(s) in the bootstrapper.
Extend Prism to make use of a stackpanel with this simple solution:
You can use the same technique with a gird or other container control, simply register your adapter(s) in the bootstrapper.
Usually the event pattern used by C# devs would be something long these lines:
When actually this provides for a cleaner threadsafe implementation:
Thanks to Rob Eisenberg for the suggestion!
Remember the event keyword is just a modifier for a delegate declaration that allows it to be included in an interface, constraints it invocation from within the class that declares it, provides it with a pair of customisable accessors (add and remove) and forces the signature of the delegate (Object sender, EventArgs e).
In Expression Blend you can convert any object to a path: Object Menu > Path > Convert to Path.
ClickOnce installer | http://stevenhollidge.com/blog-source-code/clickonce/text2path/Text2Path.html |
Source code | https://github.com/stevenh77/Text2Path |
<Controls:MetroWindow x:Class="Text2Path.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Text2Path"
Height="500"
Width="660"
ShowMinButton="False"
ShowMaxRestoreButton="False"
ShowIconOnTitleBar="true"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro">
<Controls:MetroWindow.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colours.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="Resources/Icons.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="ComboBox">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Margin" Value="10"/>
</Style>
<Style TargetType="TextBox">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="Height" Value="30" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="Height" Value="30" />
</Style>
</ResourceDictionary>
</Controls:MetroWindow.Resources>
<Controls:MetroWindow.WindowCommands>
<Controls:WindowCommands>
<Button x:Name="BlogButton" Content="blog" Click="BlogButton_Click" />
</Controls:WindowCommands>
</Controls:MetroWindow.WindowCommands>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="100" />
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<TextBlock Text="Text:" Grid.Column="0" Grid.Row="0" />
<TextBox x:Name="TextTextBlock" Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="3" />
<Button x:Name="ConvertButton" Grid.Column="4" Grid.Row="0" Content="Convert" Click="ConvertButton_Click" VerticalAlignment="Top" Margin="10"/>
<TextBlock Text="Culture:" Grid.Column="0" Grid.Row="1" />
<ComboBox x:Name="CultureComboBox" Grid.Column="1" Grid.Row="1" />
<TextBlock Text="Direction:" Grid.Column="2" Grid.Row="1" />
<ComboBox x:Name="DirectionComboBox" Grid.Column="3" Grid.Row="1" IsReadOnly="True" />
<TextBlock Text="Font:" Grid.Column="0" Grid.Row="2" />
<ComboBox x:Name="FontComboBox" Grid.Column="1" Grid.Row="2" />
<TextBlock Text="Font Size:" Grid.Column="2" Grid.Row="2" />
<ComboBox x:Name="FontSizeComboBox" Grid.Column="3" Grid.Row="2" />
<TextBlock Text="Result:" Grid.Row="3" VerticalAlignment="Top" Visibility="Collapsed"/>
<Path x:Name="OutputPath" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3"
Stroke="Black" Fill="Black"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<TextBlock x:Name="PathTextBlock" Text="Path:" Grid.Row="4" VerticalAlignment="Top" Visibility="Collapsed"/>
<TextBox x:Name="OutputTextBox" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="4"
IsReadOnly="True"
VerticalAlignment="Stretch"
Visibility="Collapsed"
TextWrapping="WrapWithOverflow"
FontSize="12"
Height="180"/>
<Button x:Name="CopyButton" Visibility="Collapsed" Grid.Column="4" Grid.Row="4" Content="Copy" Click="CopyButton_Click" VerticalAlignment="Top" Margin="10"/>
<TextBlock x:Name="ClipboardResponse" Grid.Column="4" Grid.Row="4" VerticalAlignment="Top" HorizontalAlignment="Center" FontSize="12" Foreground="Red" Margin="0,60,0,0"/>
</Grid>
</Controls:MetroWindow>
using System;
using System.Collections;
using System.Drawing.Text;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace Text2Path
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
Populate();
SetDefaults();
}
private void Populate()
{
CultureComboBox.ItemsSource = Helper.GetAvailableCultures();
DirectionComboBox.ItemsSource = Helper.GetDirections();
FontComboBox.ItemsSource = Helper.GetFonts();
FontSizeComboBox.ItemsSource = Helper.GetFontSizes();
}
private void SetDefaults()
{
TextTextBlock.Text = "Convert this text!";
CultureComboBox.SelectedItem = "en-US";
DirectionComboBox.SelectedItem = "Left to right";
FontComboBox.SelectedItem = "Segoe UI";
FontSizeComboBox.SelectedItem = "48";
}
private void ConvertButton_Click(object sender, RoutedEventArgs e)
{
try
{
this.Cursor = Cursors.Wait;
var path = Helper.Text2Path(TextTextBlock.Text,
CultureComboBox.Text,
(DirectionComboBox.Text == "Left to right"),
FontComboBox.Text,
Int32.Parse(FontSizeComboBox.Text));
OutputTextBox.Text = string.Format("<Path Stroke={0}Black{0} Fill={0}Black{0} Data={0}{1}{0} />", '"', path);
PathTextBlock.Visibility = Visibility.Visible;
CopyButton.Visibility = Visibility.Visible;
OutputPath.Data = Geometry.Parse(path);
}
catch (Exception ex)
{
OutputTextBox.Text = ex.Message;
}
finally
{
OutputTextBox.Visibility = Visibility.Visible;
this.Cursor = Cursors.Arrow;
}
}
private void BlogButton_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Process.Start("http://stevenhollidge.blogspot.com");
}
private void CopyButton_Click(object sender, RoutedEventArgs e)
{
try
{
Clipboard.SetData(DataFormats.Text, OutputTextBox.Text);
ClipboardResponse.Text = "Success";
}
catch
{
ClipboardResponse.Text = "Failed";
}
}
}
public class Helper
{
public static string Text2Path(String text, string culture, bool leftToRight, string font, int fontSize)
{
if (culture == "") culture = "en-us";
var ci = new CultureInfo(culture);
var fd = leftToRight ? FlowDirection.LeftToRight : FlowDirection.RightToLeft;
var ff = new FontFamily(font);
var tf = new Typeface(ff, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
var t = new FormattedText(text, ci, fd, tf, fontSize, Brushes.Black);
var g = t.BuildGeometry(new Point(0, 0));
var p = g.GetFlattenedPathGeometry();
return p.ToString();
}
public static IEnumerable GetAvailableCultures()
{
return CultureInfo.GetCultures(CultureTypes.SpecificCultures | CultureTypes.NeutralCultures)
.Select(x => x.Name)
.ToList();
}
public static IEnumerable GetDirections()
{
return new [] {"Left to right", "Right to left" };
}
public static IEnumerable GetFonts()
{
return new InstalledFontCollection().Families.Select(font => font.Name).ToList();
}
public static IEnumerable GetFontSizes()
{
return new [] { 8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 26, 28, 36, 48, 72 }.Select(x => x.ToString());
}
}
}
I’ve just stumbled across the GeoBat font which gives you map images – pretty cool!
Here is an example of a simple custom markup extension.
The custom markup extension is bound to the text property of a textblock with both parameters hardcoded for this example: Value1 = 10 and Value2 = 20.
Giving us the result of:
Silverlight5 source code here:
http://stevenhollidge.com/blog-source-code/SimpleCustomMarkupExtension-Calculator.zip
Always good to check out other Silverlight apps for inspiration, layout designs and widget styles.
This custom framework contains the following functionality:
Client
Server
Silverlight Application Framework demo from Steven Hollidge on Vimeo.
The Ribbon button has a tag property that has the desired Uri set as its content.
When the button is clicked, a message is sent that contains the desired Uri.
The messenger listener receives the message and calls the ContentFrame.NavigateTo method.
Click here to download the source code:
http://stevenhollidge.com/blog-source-code/SilverlightExampleApp.zip
If you prefer the style of a Tree View menu, which is free compared to the Ribbon which is licensed, you can check out my blog posting here.
http://stevenhollidge.blogspot.com/2011/06/treeview-menu-for-silverlight.html