Archive
HowTo: Set UI language (CurrentUICulture) in Silverlight
At LvS (the opensource application of LeViS), I’ve been using this (VB.net) code to set the UI language (for example to Greek):
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("el")
Others seem to have been using (C# – that’s why there is a trailing semicolon):
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("el");
assuming System.Globalization and System.Threading namespaces have been imported.
However, now that I’m building ClipFlair in Silverlight (http://clipflair.codeplex.com), I noticed both GetCultureInfo and CreateSpecificCulture aren’t exposed to Silverlight. Seems one needs for example to modify their App.xaml to use new CultureInfo("el") to do something like below (see parts in bold):
… using System.Globalization; using System.Threading; …
private void Application_Startup(object sender, StartupEventArgs e)
{
CultureInfo c = new CultureInfo("el");
Thread.CurrentThread.CurrentCulture = c;
Thread.CurrentThread.CurrentUICulture = c;
this.RootVisual = new MainPage();
}
Alternatively you can set at each XAML page/control the “language” attribute of the “UserControl” element.
If you want to enable dynamic on-the-fly localization based on end-user selection of UI language at runtime (say via a drop-down box), checkout a nice solution (the “Localizer” one) at:
http://stackoverflow.com/questions/3992007/how-to-switch-ui-culture-of-data-binding-on-the-fly-in-silverlight
Zoom and Pan control for WPF and Silverlight (via WPF compatibility layer)
I’ve managed to combine
http://www.codeproject.com/Articles/85603/A-WPF-custom-control-for-zooming-and-panning
and a cut-down version of it for Silverlight that was out there:
http://www.codeproject.com/Articles/167453/A-Silverlight-custom-control-for-zooming-and-panni
I did it in a way that the Silverlight version is source-code compatible with the WPF version (via a WPF compatibility layer that even implements value coercion), so that both the WPF and the Silverlight projects share the same source code files.
The resulting libraries for WPF and Silverlight work with the existing samples (from the two articles mentioned above) without any changes to them.
Can checkout the latest version (plan to add the samples there too for convenience) under the "Client" subfolder of ClipFlair source-code base at http://clipflair.codeplex.com
InitializeError Message: Failed to load a platform extension in Silverlight
If you get an error like:
Unhandled Error in Silverlight Application Code: 2153 Category: InitializeError Message: Failed to load a platform extension. Possibly corrupt or invalid file: …
when you try to launch your Silverlight application (especially if you have the project set to use an autogenerated test page), you should read:
http://forums.silverlight.net/t/185747.aspx/1
In my case the suggestion to turn off “Reduce XAP size by using application library caching” setting at the Silverlight library project settings fixed the issue.
I was using the internal Visual Studio development web server (Cassini), but some people at the discussion thread above also say it can occur in IIS7, with the problem actually being in compression settings (need to turn off option "Enable dynamic content compression”) and they point to the following discussion:
IsolatedStorageSettings for WPF
System.IO.IsolatedStorageSettings doesn’t exist in WPF (only in Silverlight) but can easily be ported from Mono project’s Moonlight implementation (the Moonlight project home is at http://www.mono-project.com/Moonlight), as suggested at: http://groups.google.com/group/wpf-disciples/browse_thread/thread/4ed6c009f3fb7d69
I found that implementation at the following URL:
Did some modifications to IsolatedStorageSettings.cs to make it work with WPF (whether the application is deployed via ClickOnce or not):
// per application, per-computer, per-user
public static IsolatedStorageSettings ApplicationSettings {
get {
if (application_settings == null) {
application_settings = new IsolatedStorageSettings (
(System.Threading.Thread.GetDomain().ActivationContext!=null)?
IsolatedStorageFile.GetUserStoreForApplication() :
//for WPF, apps deployed via ClickOnce will have a non-null ActivationContext
IsolatedStorageFile.GetUserStoreForAssembly());
}
return application_settings;
}
}
// per domain, per-computer, per-user
public static IsolatedStorageSettings SiteSettings {
get {
if (site_settings == null) {
site_settings = new IsolatedStorageSettings (
(System.Threading.Thread.GetDomain().ActivationContext!=null)?
IsolatedStorageFile.GetUserStoreForApplication() :
//for WPF, apps deployed via ClickOnce will have a non-null ActivationContext
IsolatedStorageFile.GetUserStoreForAssembly());
//IsolatedStorageFile.GetUserStoreForSite() works only for Silverlight
}
return site_settings;
}
}
Note that you should also change the #if block at the top of that code to write
#if !SILVERLIGHT
Also can take a look at the following for custom settings storage:
http://f10andf11.blogspot.gr/2012/03/wpf-implement-isolatedstoragesettings.html
The resulting IsolatedStorageSettings.cs file for WPF (thanks to if !SILVERLIGHT block, the C# compiler will ignore it in Silverlight which has such class already) is included in the WPF_Compatibility layer at the ClipFlair source-code in http://clipflair.codeplex.com (checkout the “Client” subfolder in the source).
The WPF compatibility layer contains other goodies too like value coercion for Silverlight DependencyProperties using WPF-compatible syntax, so that your source code can stay source-level compatible with both WPF and Silverlight and be shared among respective projects.
HowTo: Load a XAML ResourceDictionary from a .NET assembly
Copying here my answer at:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/11a42336-8d87-4656-91a3-275413d3cc19
What seems to work for me is the following (copying from the source code of http://ClipFlair.codeplex.com [check out the FlipPanel project under “Client” subfolder])
note
I’m using Build Action = "Page" and Custom Tool="MSBuild:Compile" at the properties of Themes\DropDownTheme.xml and Themes\RotateHorizontalTheme.xaml, as was for Themes\Generic.xaml. Seems to work OK (probably this is faster at runtime compared to setting Build Action to Resource and telling it to not build it)
according to http://stackoverflow.com/questions/145752/what-are-the-various-build-action-settings-in-vs-net-project-properties-and-wh the Build Action = "Page" compiles the XAML into BAML (this seems to also apply to Silverlight 5)
* FlipPanel project, Themes\Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FlipPanel;assembly=FlipPanel">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/FlipPanel;component/Themes/RotateHorizontalTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="local:FlipPanel">
<Setter Property="Template"
Value="{StaticResource FlipPanel_RotateHorizontalTemplate}"/>
</Style>
</ResourceDictionary>
* FlipPanel Project, Themes\RotateHorizontalTheme.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:FlipPanel;assembly=FlipPanel"> <ControlTemplate x:Key="FlipPanel_RotateHorizontalTemplate"
TargetType="local:FlipPanel"> <Grid> ... </Grid> </ControlTemplate> <Style x:Key="FlipPanel_RotateHorizontalStyle" TargetType="local:FlipPanel"> <Setter Property="Template"
Value="{StaticResource FlipPanel_RotateHorizontalTemplate}"/> </Style> </ResourceDictionary>
* FlipPanel Project, Themes\DropDownTheme.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:FlipPanel;assembly=FlipPanel"> <ControlTemplate x:Key="FlipPanel_DropDownTemplate"
TargetType="local:FlipPanel"> <Grid> ... </Grid> </ControlTemplate> <Style x:Key="FlipPanel_DropDownStyle" TargetType="local:FlipPanel"> <Setter Property="Template"
Value="{StaticResource FlipPanel_DropDownTemplate}"/> </Style> </ResourceDictionary>
* FlipPanel.Silverlight.Demo project, FlipPanelTest.xaml
<UserControl x:Class="FlipPanelTest.FlipPanelTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:flip="clr-namespace:FlipPanel;assembly=FlipPanel" >
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/FlipPanel;component/Themes/RotateHorizontalTheme.xaml" />
<ResourceDictionary
Source="/FlipPanel;component/Themes/DropDownTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" Width="400">
<Grid.RowDefinitions>
<RowDefinition Height="300"></RowDefinition>
<RowDefinition Height="300"></RowDefinition>
</Grid.RowDefinitions>
<flip:FlipPanel x:Name="panel1" Grid.Row="0" BorderBrush="DarkOrange"
BorderThickness="3"
CornerRadius="4" Margin="10" Background="White"
Template="{StaticResource FlipPanel_DropDownTemplate}" >
<!-- Style="{StaticResource FlipPanel_DropDownStyle}" -->
<flip:FlipPanel.FrontContent>
<StackPanel Margin="6">
<TextBlock TextWrapping="Wrap" Margin="3" FontSize="16"
Foreground="DarkOrange"
>This is the front side of the FlipPanel.</TextBlock>
<Button Margin="3" Padding="3" Content="Button One"></Button>
<Button Margin="3" Padding="3" Content="Button Two"></Button>
<Button Margin="3" Padding="3" Content="Button Three"></Button>
<Button Margin="3" Padding="3" Content="Button Four"></Button>
</StackPanel>
</flip:FlipPanel.FrontContent>
<flip:FlipPanel.BackContent>
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Margin="3" FontSize="16"
Foreground="DarkMagenta"
>This is the back side of the FlipPanel.</TextBlock>
<Button Grid.Row="2" Margin="3" Padding="10"
Content="Flip Back to Front" HorizontalAlignment="Center"
VerticalAlignment="Center" Click="cmdFlip1_Click"></Button>
</Grid>
</flip:FlipPanel.BackContent>
</flip:FlipPanel>
<flip:FlipPanel x:Name="panel2" Grid.Row="1" BorderBrush="DarkOrange"
BorderThickness="3"
CornerRadius="4" Margin="10" Background="White"
Template="{StaticResource FlipPanel_RotateHorizontalTemplate}" >
<!-- Style="{StaticResource FlipPanel_RotateHorizontalStyle}" -->
<flip:FlipPanel.FrontContent>
<StackPanel Margin="6">
<TextBlock TextWrapping="Wrap" Margin="3" FontSize="16"
Foreground="DarkOrange"
>This is the front side of the FlipPanel.</TextBlock>
<Button Margin="3" Padding="3" Content="Button One"></Button>
<Button Margin="3" Padding="3" Content="Button Two"></Button>
<Button Margin="3" Padding="3" Content="Button Three"></Button>
<Button Margin="3" Padding="3" Content="Button Four"></Button>
</StackPanel>
</flip:FlipPanel.FrontContent>
<flip:FlipPanel.BackContent>
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Margin="3" FontSize="16"
Foreground="DarkMagenta"
>This is the back side of the FlipPanel.</TextBlock>
<Button Grid.Row="2" Margin="3" Padding="10"
Content="Flip Back to Front" HorizontalAlignment="Center"
VerticalAlignment="Center" Click="cmdFlip2_Click"></Button>
</Grid>
</flip:FlipPanel.BackContent>
</flip:FlipPanel>
<flip:FlipPanel x:Name="panel3" Grid.Row="2" BorderBrush="DarkOrange"
BorderThickness="3"
CornerRadius="4" Margin="10" Background="White" >
<!-- using default style here -->
<flip:FlipPanel.FrontContent>
<StackPanel Margin="6">
<TextBlock TextWrapping="Wrap" Margin="3" FontSize="16"
Foreground="DarkOrange"
>This is the front side of the FlipPanel.</TextBlock>
<Button Margin="3" Padding="3" Content="Button One"></Button>
<Button Margin="3" Padding="3" Content="Button Two"></Button>
<Button Margin="3" Padding="3" Content="Button Three"></Button>
<Button Margin="3" Padding="3" Content="Button Four"></Button>
</StackPanel>
</flip:FlipPanel.FrontContent>
<flip:FlipPanel.BackContent>
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Margin="3" FontSize="16"
Foreground="DarkMagenta"
>This is the back side of the FlipPanel.</TextBlock>
<Button Grid.Row="2" Margin="3" Padding="10"
Content="Flip Back to Front" HorizontalAlignment="Center"
VerticalAlignment="Center" Click="cmdFlip2_Click"></Button>
</Grid>
</flip:FlipPanel.BackContent>
</flip:FlipPanel>
</Grid>
</UserControl>
Note that I decided to prefix names with "FlipPanel_", not sure if there’s some better way (using XAML namespaces somehow) to avoid any conflicts when merging the dictionaries and resolving the resouces with "{StaticResource …}"
Also note that in each theme file I also provide a Style (that sets the corresponding Template property of the FlipPanel conrol) that one can use instead of using the Template directly. At that Style more FlipPanel control properties could be set to values appropriate for that template (the template defines a skeleton and the style dresses the pirate [skeleton] as somebody cleverly pointed out).
Note that Generic.xaml merges and uses the templat from one of the themes. Couldmake copies of files similar to Generic.xaml and reference the same template but with different values in the Style for other properties to make variations without resorting to Copy/Paste when multiple Themes use the same Template but restyle it a bit.
Another important note is that at Generic.xaml you must not use x:Key="FlipPanel_DefaultStyle" or anyother key at the default style, or the command
public FlipPanel()
{
DefaultStyleKey = typeof(FlipPanel);
}
won’t load the default style (which is needed when you don’t provide a Template or Style value at the consumer XAML (FlipPanelTest.xaml). Probably one can modify it to load a style by name instead of just by type (probably the issue was that it found multiple named styles applying to that type [both FlipPanel_RotateHorizontalStyle and FlipPanel_DefaultStyle] in the Generic.xaml), but removing the Key and using an unnamed style seems to do the trick.
What to do if Generic.xaml doesn’t get loaded for WPF control
Just came across http://wangmo.wordpress.com/2007/09/27/themesgenericxaml/ which gave me a hint on why a WPF control wasn’t getting instantiated correctly when loaded from an external assembly (dll):
to load generic.xaml for WPF, at the start of Properties\AssemblyInfo.cs you need (note this isn’t used/needed in Silverlight):
using System.Windows;
and at the end of Properties\AssemblyInfo.cs you need:
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
Mind you that if the project doesn’t show a Properties node in Solution Explorer, you have to either make a new project using the correct template (for a WPF custom control), or right click the project, select Properties, then press the Assembly Information button and enter some dummy values, then OK to create the Properties node (which also creates to a Properties subfolder and AssemblyInfo.cs file).
You can expand (drop-down) the special Properties node in solution explorer then to open AssemblyInfo.cs and add the above stuff if missing.
Fix: compile CSpeex audio codec at Silverlight 4 RC+ and Silverlight 5
Just added an issue to CSpeex project – http://cspeex.codeplex.com/workitem/18209 – with some fixes to make it compile for Silverlight 4 RC and higher (was for Silverlight 4 Beta).
1) at "MainPage.xaml.cs", replace with this method implementation:
private void TakeSnapshot_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
// capture the current frame and add it to our observable collection
_captureSource.CaptureImageCompleted += (source, eventargs) =>
{
_images.Add(eventargs.Result);
};//”ImageCaptureAsync" method replaced by "CaptureImageAsync" at Silverlight 4 RC
_captureSource.CaptureImageAsync();
}
}
2) at "StreamAudioSync.cs" do this small change:
protected override void OnFormatChange(AudioFormat audioFormat)
{
if (audioFormat.WaveFormat == WaveFormatType.Pcm)//”PCM" renamed to "Pcm" at Silverlight 4 RC (after SL4beta)
{
…
Note that the CSpeex-SL project won’t load if you don’t have Silverlight 3 SDK installed. After loading you can open up properties of that project and of SLAudioDemo one and set the target to Silverlight 5 from Silverlight 3, then save those two projects and rebuild the solution.
Validating E-mails using Regular Expressions in Java
To sum up the discussion at http://stackoverflow.com/questions/1360113/is-java-regex-thread-safe/, you can reuse (keep in static variables) the compiled Pattern(s) and tell them to give you new Matchers when needed to validate those regex pattens against some string:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Validation helpers
*/
public final class Validators {
private static final String EMAIL_PATTERN =
"^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*
@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$";
private static Pattern email_pattern;
static {
email_pattern = Pattern.compile(EMAIL_PATTERN);
}
/**
* Check if e-mail is valid
*/
public static boolean isValidEmail(String email) {
Matcher matcher = email_pattern.matcher(email);
return matcher.matches();
}
}
(Note: the EMAIL_PATTERN string should be put in a single line)
For the RegEx pattern used, see the article at http://www.mkyong.com/regular-expressions/how-to-validate-email-address-with-regular-expression/ and the user comments (and useful links) posted there.
Update (20120715): previous pattern wasn’t accepting “-” in the domain name