Localization for Winforms from designmode? - c#

I need to bind labels or items in a toolstrip to variables in Design Mode.
I don't use the buit-in resources not the settings, so the section Data is not useful. I am taking the values out from an XML that I map to a class.
I know there are many programs like:
http://www.jollans.com/tiki/tiki-index.php?page=MultilangVsNetQuickTourForms
but they work with compiled resx. I want to use not compiled XML.
I know that programatically i can do it, i create a method (for example, UpdateUI()), and there I assign the new values like this:
this.tsBtn.Text=Class.Texts.tsBtnText;
I would like something i could do from Design Mode or a more optimized way than the current one. Is there any Custom Control out there or Extension?

Aleksandar's response is one way to accomplish this, but in the long run it's going to be very time consuming and won't really provide much benefit. The bigger question that should be asked is why do you not want to use the tools and features built-in to .NET and Visual Studio or at least use a commercial third-party tool? It sounds like you are spending (have spent?) a lot of time to solve a problem that has already been solved.

Try with inheriting basic win controls and override OnPaint method. Example bellow is a button that has his text set on paint depending on value contained in his Tag property (let suppose that you will use Tag property to set the key that will be used to read matching resource). Then you can find some way to read all cache resource strings from xml files (e.g. fictional MyGlobalResources class.
public class LocalizedButton : Button
{
protected override void OnPaint(PaintEventArgs pevent)
{
base.OnPaint(pevent);
this.Text = MyGlobalResources.GetItem(this.Tag.ToString());
}
}

You can use satellite assemblies for localization and generate them using your XML file as a source for the translated entities.
more about satellites http://msdn.microsoft.com/en-us/library/21a15yht(VS.71).aspx
sure it's not from design mode, but there's no way to do it this way with your restrictions.

Related

WPF Localization using an static method

I have a C# .Net 4.5 WPF application.
The application have to be localizable. Which means I have to be able to change the labels/titles/button/text of everything visual in my application.
I have an existing model to take an id-String and return the text for the given language. Something like:
String localizedCancelText = Localize.Text("#Cancel"); //Cancel
String localizedMoneyLeftText = Localize.Text("#MoneyLeft",10); //$10 left
Where the Localize.Text(..) method is static.
This works all nicely.
The problem is with the labels/titles, thoses are set in WPF.
The idea is to have all labels(all visual) containing keywords insteed of english text. For example a WPF cancel button would be like:
<Button Content="#Cancel"/>
And then I have to take the "#Cancel" and lookup how cancel is written in the given language/location/department.
My question is:
How can I do this? I can set every label/button/text from codebehind, but that would be a ugly solution. I would much rather set it in WPF as shown above, and then "somehow" transelate the #Cancel using the Localize.Text(..) method to get the actual cancel text for the given language/location/department.
We use a software called Sisulizer that can parse the WPF and extract localizable strings. It can do that for all resources for that matter. We simply import all our resources into Sisulizer and the from there we export a csv file with required translations which we give our translators. Sisulizer builds satelite resource Dlls which we then use in our software.
it's better to use resource file .resx extension.you have to declare label and value in resx file.
My solution is based on this:
http://www.thomaslevesque.com/2009/07/28/wpf-a-markup-extension-that-can-update-its-target/
http://www.thomaslevesque.com/2009/08/23/wpf-markup-extensions-and-templates/
which allows me to use
<Button Content="{markUp:Localized Key=#BigButton}">
And still be able to change the language at runtime.

How to specify order of debugger visualizers in Visual Studio

I've been working on a debugger visualizer for Visual Studio for some time and while the actual visualizer works fine. The problem is that it always places itself at the top of the visualizer list when examining a variable which really annoys some of the users who rather have Text as the top one (since the top one is also default when opening VS).
I can't find any support for this on DialogDebuggerVisualizer or DebuggerVisualizerAttribute which were my first thoughts so I've been scouring SO/MSDN/Google for information on how to affect the sort order of the visualizers (preferably to put mine last in the list) but to no avail.
Below is how I register my visualizer, it then just shows a form based on the value that is being visualized.
using Microsoft.VisualStudio.DebuggerVisualizers;
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(Shorthand.VSAddins.JsonVisualizer.JsonVisualizer),
typeof(VisualizerObjectSource),
Target = typeof(string),
Description = "Json Visualizer")]
namespace Shorthand.VSAddins.JsonVisualizer
{
public class JsonVisualizer : DialogDebuggerVisualizer
{
protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
{
var json = objectProvider.GetObject() as string;
var form = new VisualizerForm { Json = json };
windowService.ShowDialog(form);
}
}
}
Does anyone know if it is possible to affect the order of the visualizers or should I just let it be?
I don't think there is a solution. But there is a workaround:
Define your own Text Visualizer and put appropriate DebuggerVisualizer attribute before the attribute of your JsonVisualizer. The result will be that string will be readable by default and Json Visualizer can be chosen. A window with a multi-line textbox is not too much work.
It is probably not even necessary to write visualizer. It should be possible to use internal one but I don't know its name (Which class is used for "Text Visualizer"?).
It will always appear first, by design. The under the hood cast has found the best match for the variable it is reflecting on.
however, you could do either of two things. You could make the visualizer only appear when the sting contains ':'
Or you could use reflection to reorder the visualisers by adding them to the end of the collection in the order you want, then removing the originals from the collection.
For the latter you will most likely have to change the collection from readonly to writable. Via reflection.
There is no reliable source to draw on other than your will to succeed.
I guess that VS 'under the hood' can distinguish between type of string and type of xml quite easily, but Xml is just a string too, so a key question here would be, how does VS tell the difference between the two?
Could you dissect the VS XML visualizer to see how it works (even if you have to use reflector on the DLL to do it, you might get to see the method that works it out)

How to check if a XAML element supports AutomationId attribute

I need a way to check that every WPF control in my codebase has an AutomationProperties.AutomationId attribute. (This is needed for automated UI testing.) I also need to make sure this requirement is enforced in the future on all future forms which may be added to the codebase. I have thought through a few different approaches, and so far none of them seem like the right approach.
Option 1: Write unit tests for every WPF form in the application.
This is a fairly easy approach. I have already written a method which checks all the logical descendants of a DependencyControl and makes sure each descendant has an AutomationId. Here's some C#:
private bool AllControlsHaveAutomationId(DependencyObject control)
{
bool result = true;
if (this.ControlHasAutomationId(control))
{
foreach (object o in LogicalTreeHelper.GetChildren(control))
{
FrameworkElement frameworkElement = o as FrameworkElement;
if (frameworkElement != null)
{
result = this.AllControlsHaveAutomationId(frameworkElement);
}
}
}
else
{
result = false;
}
return result;
}
private bool ControlHasAutomationId(DependencyObject control)
{
return !string.IsNullOrEmpty(AutomationProperties.GetAutomationId(control));
}
The problem with this approach is that I would be assuming that other developers would write unit tests for their forms, which is not a good assumption. If I can't assume that AutomationIds will be added to all WPF controls, then I can't assume that the unit tests will be written, either.
Option 2: Read each XAML file using System.Xml.XmlDocument. Check the elements in the document for AutomationProperties.AutomationId.
This approach seems promising. My original plan was to load each XAML file into an XmlDocument and check the AutomationProperties.AutomationId attribute for each element in the document. However, I realized that not every element type in XAML supports the AutomationProperties.AutomationId attribute. What I need is a way to read an element in a XAML file and determine if the element supports the AutomationProperties.AutomationId attribute. Is there a way to do this?
You could look at the BAML (compiled XAML) in all of the assemblies of your codebase....there are various ways to do that.
Looking at BAML via .NET Reflector and an AddIn
One way of doing that would be to write a Reflector add-in.
You could perhaps base it off the BAML Viewer which is already available.
http://reflectoraddins.codeplex.com/wikipage?title=BamlViewer&referringTitle=Home
http://wpf.2000things.com/tag/baml/
Then hopefully it would just be a case of giving reflector your assemblies and saying find me things without Automation IDs.
Looking at BAML via StylesExplorer
http://stylesexplorer.codeplex.com/
Allows you to access the BAML in an assembly with a BamlAssembly class.
Looking at BAML via LocBAML
http://msdn.microsoft.com/en-us/library/ms746621.aspx
http://bloc.codeplex.com/releases/view/44124 (related link)
The source code to the tool is available in the Windows SDK. You could modify to look for the automation properties instead of localizable ones.
Using XamlReader.Load()
You might even get somewhere with just XamlReader.Load() on its own with your uncompiled .xaml files.
http://go4answers.webhost4life.com/Example/xamlreaderloadbaml-removed-125290.aspx
Using XamlReader.LoadBaml()
http://wpftutorial.net/baml.html
Other Options
A runtime verifier of various Automation
http://acccheck.codeplex.com/releases/view/46527

(.net) Kind of design question

My typical application has a couple of textboxes, checkbuttons, radiobuttons, and so. I always want to load the settings the user used the last time when the program starts, and also want to save the settings as the users clicks "Save settings" or closes the application. When the user attempts to save the settings, I'll have to check each of the controls for input errors (sometimes they have to have a max length, other times only caps, other times other things, there isn't a rule for them all, everytime it'll be different), and only if everything's OK i'll let him save the options. If there is something wrong, no option is saved and my errorcontrol provider will pop up a description of the input type info that should be put in that control.
I've been designing this from scratch for all my projects, but it's being a pain to do it. So I'd thought maybe now was the time to do some library to help me. I thought initially that maybe it'd be a good idea to have all the controls on my form that are going to be part of this save/load process to have an attribute associated with them, something like this
public delegate bool InputIsOkHandler();
public class OptionsAttribute : Attribute {
public Control controlRef;
public InputIsOkHandler IsInputOk;
public string errorMessageToShowOnErrorProvider;
public OptionsAttribute(Control controlRef, InputIsOkHandler inputHandler, string errMessage) {
...
}
}
The main problem here is that when I declare the attribute on a given var:
[Options(...)]
TextBox textBox1 = new TextBox();
I'll get
Error 1 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.
So I guess this approach isn't the best one. What would you guys do in this situation? Would you use attributes? Would you use other mechanisms?
Thanks
Do you know that .NET already includes such a system since 2.0? See MSDN, CodeProject and this white paper from WestWind.
The Personalization and User Profiles supported in ASP.NET 2.0 can be a nice way to achieve your goal.
You can check this MSDN article for a overview Personalization in ASP.NET 2.0

User Control Property Designer Properties

For a C# UserControl on Windows Mobile (though please answer if you know it for full Windows...it might work) how do you change what shows up in the Designer Properties window for one of the Control's public Properties. For example:
private Color blah = Color.Black;
public Color Blah
{
get { return this.blah; }
set { this.blah = value; }
}
This shows up for the control, but it's in the "Misc" category and has no description or default value. I've tried using the settings in System.ComponentModel like "DesignerCategory", such as:
[DesignerCategory("Custom")]
But says this is only valid for class declarations... could've sworn it was the System.ComponentModel items I used before...
Update:
#John said:
DesignerCatogy is used to say if the
class is a form, component etc.
Try this:
[Category("Custom")]
Is there a particular namespace I need to use in order to get those?
I've tried those exactly and the compiler doesn't recognize them.
In .NETCF all I seem to have available from System.ComponentModel is:
DataObject,
DataObjectMethod,
DefaultValue,
DesignerCategory,
DesignTimeVisible,
EditorBrowsable
The only one it doesn't scream at is EditorBrowsable
DesignerCategory is used to say if the class is a form, component etc.
For full windows the attribute you want is:
[System.ComponentModel.Category("Custom")]
and for the description you can use [System.ComponentModel.Description("This is the description")]
To use both together:
[System.ComponentModel.Category("Custom"),System.ComponentModel.Description("This is the description")]
However this is part of system.dll which may be different for windows mobile.
Is this of use to you? I am not into CF development, but it looks like you need to add some XML metadata to enable it:
http://blogs.msdn.com/bluecollar/archive/2007/02/08/adding-compact-framework-design-time-attributes-or-more-fun-with-textboxes.aspx
Interesting read.. Looks like a lot of design time support was stripped out of CF because you dont design them on the devices.. Which seems kinda weird to me.. Cant imagine using a handheld as a development rig!
Scroll down about half way for the good stuff ;)
The article does not suggest that anyone is designing ON the device. However, when you create a Compact Framework project, the compact framework (for your desktop PC) is used to handle design time rendering. If you think about it that is what you expect. The same framework (or nearly so) is used to do the rendering both on your PC at design time and later on the device at runtime. The issue is that the design time attributes were not added to the compact framework (I assume to reduce the size).

Categories

Resources