WPF Converter Static Text - wpf

I'm trying to implement my own Translator using Converters. In the converter I call a static class containing translations. This translations are loaded when application starts.
The main advantage using this converters for me are three:
I translate texts in runtime, based on XML language files.
When executing application I register text without translation in other XML file, so I can later add the translation.
Translations are applied also to data when desired.
All works fine when the text to translate comes from a binded property, per example:
<TextBox Grid.Row="1" Text="{Binding NameToShow, Converter={StaticResource TranslationConverter}}"></TextBox>
The problem is translating static text like labels, button content... The idea is making something like this:
<Button Content={Binding "MyText",Converter={StaticResource TranslationConverter}} Command="{Binding InitializeAdapterCommand}"></Button>
Obviously, I want neither to declare static strings in resources or to use bindable properties.
Any suggestions?

you can use Binding.Source property to pass a const value to a converter:
Text="{Binding Source='My Text', Converter={StaticResource TranslationConverter}}"

You can create your own MarkupExtension instead of relying on Bindings:
public class StaticTranslation : MarkupExtension
{
public StaticTranslation()
{
}
public StaticTranslation(string textToTranslate)
{
TextToTranslate = textToTranslate;
}
public string TextToTranslate { get; set; }
public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (Converter != null)
{
return Converter.Convert(TextToTranslate, typeof(string), ConverterParameter, CultureInfo.CurrentUICulture);
}
return TextToTranslate;
}
}
And use it with lib being the xmlns:lib=[namespace containing StaticTranslation]
<TextBlock Text="{lib:StaticTranslation 'ABC',Converter={StaticResource TranslationConverter}}"/>
Ofcourse the converter usage in StaticTranslation is just an example. You may want to test / improve the code for production usage.
Side note:
If you get an error when nesting Converter={StaticResource TranslationConverter}, move your markup extension to a separate class library project. See the following: https://stackoverflow.com/a/11785549/5265292

Related

Bind Textbox Text to a Static Property

I have a Static Class with the following Static Property:
public static class PrintingMethods
{
public static String DocsCountString
{
get
{
return printDocuments.Count.ToString();
}
}}
I have a text box that I bind to this property:
<TextBlock Text="{x:Static my:PrintingMethods.DocsCountString}" x:Name="PagesNumber"/>
This works - I can see the number in the Text, But it never changes If the Property Value Change.
I am quite new to this, I know there are things like Dependency Object and INotify Interface but this won't work for Static.
If anyone can help me with a working code (modification to what I wrote) to Achieve real time textChange that would be great, Thanks!!!
Answer on our comments:
If you use the Singleton Pattern, you can bind to it like that
public sealed class MySingleton : INotifyPropertyChanged
{
public void RaiseProperty(string aPropName)
{
// implementation of INotifyPropertyChanged
}
public static MySingleton Instance
{
get{ return sInstance; }
}
public string MyProperty
{
get {return mMyProperty;}
set {mMyProperty = value; RaiseProperty("MyProperty"); }
}
private string mMyProperty;
private static MySingleton sInstance = new MySingleton();
}
As you can see you can easily use the INotifyPropertyChanged interface and implementation with a singleton class. You might want to make the constructor private to disallow creating another instance of this class. Also it would be possible to lazy allocate the MySingleton instance. You will find much more about singletons on stackoverflow.
<TextBlock Text="{Binding Source={x:Static my:MySingleton.Instance}, Path=MyProperty}"/>
The important part here now is the Binding and the overriden Source. Usually Binding takes the current DataContext. By setting a new Source the DataContext is irrelevant and the new Source is used to get the value behind the Path property.
you should use function in modifier is internal like:
Form2:
internal string foo()
{
return nom;
}
Form1:
form2 win= new form2();
win.ShowDialog();
Textbox.Text = win.foo();

Localizing in WPF

I am localizing a WPF application. The datagrid columns headers needs to be changed at runtime according to the specific UI culture in the XAML.
Though I am able to do the localization in the code behind and also in XAML by using the LocBaml tool. I am not able to achieve it with one particular scenario in the XAML. The scenario is that I am parsing XAML, as I am loading it in an XML file and parsing..
So now when I parse it like:
<dg:DataGridColumnHeader Header="{x:Static findlocale:My.Resources.String.anylocalword}"></dg:DataGridColumnHeader>
Where findlocale is the XAML namespace keyword, I am getting an error:
XAML parse error. Cannot find type My.Resources.String.localword in
the xaml namespace.
Why is this not working in this scenario? How do I overcome it?
I'm willing to bet your findlocale XML namespace is incorrect. If you have something like:
namespace MyNameSpace.MySubNamespace {
public class MyClass {
public static string MyProperty { get; set; }
}
}
Then your XML namespace must be declared like xmlns:findlocale="clr-namespace:MyNameSpace.MySubNamespace" in order to use {x:Static findlocale:MyClass.MyProperty}.
You cannot declare your XML namespace like xmlns:findlocale="clr-namespace:MyNameSpace" and use it like {x:Static findlocale:MySubNamespace.MyClass.MyProperty}.
Also, if you have any nested classes/enums, then you must use a + sign in place of the .. So if you had:
namespace MyNameSpace.MySubNamespace {
public class MyClass {
public class MyNestedClass {
public static string MyProperty { get; set; }
}
}
}
To access MyProperty, you'd need to declare your XML namespace like xmlns:findlocale="clr-namespace:MyNameSpace.MySubNamespace" and access it like {x:Static findlocale:MyClass+MyNestedClass.MyProperty}.

Silverlight: Using DataContextProxy to access ObserableCollection elements

I'm trying to get binding working in the header of a grid column which does not have access to the DataContext. To give it access, I used the DataContextProxy described here: http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx
This is a simplified version of my ViewModel:
public class ViewModel : INotifyPropertyChanged
{
private String _myString;
private ObservableCollection<TabItemViewModel> _tabItems;
public String MyString { blah... }
public ObservableCollection<TabItemViewModel> TabItems {blah... }
}
and it works for accessing the MyString using XAML like this:
<TextBlock Text="{Binding Source={StaticResource DataContextProxy}, Path=DataSource.MyString}"/>
but I'm not sure how to get it to point at the ErrorHeading inside the observable collection of TabItemViewModels...
public class TabItemViewModel : INotifyPropertyChanged
{
private string _errorHeading;
public string ErrorHeading
{
get { return _errorHeading; }
set
{
_errorHeading = value;
RaisePropertyChanged("ErrorHeading");
}
}
}
I tried it like this:
<TextBlock Text="{Binding Source={StaticResource DataContextProxy}, Path=DataSource.TabItems.ErrorHeading}"/>
but I dont think you can dig into the ObservableCollection like this - I'm not even sure how it knows which element in the collection to look at.
In your TabItemViewModel implementation, you've defined ErrorHeading two times.
At one place you write
RaisePropertyChanged("ErrorHeading");
while another place you've written
OnPropertyChanged("ErrorHeading");
Looks like there is some serious problem with your code. On the top of it, you've not implemented the interface INotifyPropertyChanged in your TabItemViewModel.
So fix these problems first. Maybe, then you would be able to do something more elegant in your code. :-)

How to combine binding from custom data context with custom markup

I want to combine binding from my custom data context which contains ViewModel class and ResourceProvider class. Custom data context is set as window DataContext.
I use it that way:
<Button x:Name="btnShow" Content="Show" Command="{Binding View.HandleShow}"/>
Which View is property from dataContext. I want to use localization by custom data context using minimum markup and set ResourceProvider from other source in code that I created my own data context
Is there any possibility to do it in something which is similar to that line of code:
<TextBlock Text="{Binding Res.Key=test}" />
My resource provider inherits from markup extension with one Property: Key.
Thanks for any advice
You can create a custom markup extension using the following code :
public class LocalizedBinding : MarkupExtension
{
public String Key { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
//use target.TargetObject and target.TargetProperty to provide value based on Key
}
}
and use it like :
<TextBlock Text="{local:LocalizedBinding Key=SomeKey}" />
I try that solution but i prefer avoid prefix local because localizedBinding came from different source and use IoC pattern because of that I create CustomDataContext

DepedencyProperty within a MarkupExtension

Is it possible to have a DependencyProperty within a MarkupExtension derived class?
public class GeometryQueryExtension : MarkupExtension
{
public XmlDataProvider Source { get; set; }
public string XPath { get; set; }
public static readonly DependencyProperty ArgumentProperty = DependencyProperty.RegisterAttached(
"Argument",
typeof(string),
typeof(GeometryQueryExtension)); // this wont work because GeometryQueryExtension is not a DependencyProperty
public string Argument
{
get
{
return (string)GetValue(ArgumentProperty); // this wont even compile because GeometryQueryExtension doesnt derive from a class which has GetValue
}
set
{
SetValue(ArgumentProperty,value);// this wont even compile because GeometryQueryExtension doesnt derive from a class which has SetValue
}
}
}
The extension is used in the following snippet.
<Label.Content>
<local:GeometryQueryExtension Source="{StaticResource shapesDS}">
<local:GeometryQueryExtension.XPath>
/Shapes/Geometry/{0}
</local:GeometryQueryExtension.XPath>
<local:GeometryQueryExtension.Argument>
<Binding XPath="Geometry"/> <!-- will throw exception when processing this bind -->
</local:GeometryQueryExtension.Argument>
</local:GeometryQueryExtension>
</Label.Content>
Is it even possible to build such an extension or am i just barking up the wrong tree ?
(the code above wont compile and run, but i posted it here to best illustrate the problem).
No, you can only add dependency properties to classes that are derived from DependencyObject, MarkupExtention is derived directly from Object
Yea.. it’s an ugly problem.. However it has a simple non intuitive answer.
Create another markup extension to get the static resource.
So instead of using {StaticResource shapesDS}
You would create a new MarkupExtension called DataSetLocator
I'm not going to write the code but the Provide value would need to return your dataset based on a name or some other input.
Then you change your xaml to have your extension use the dataset locator extension example Source="{DataSetLocator name=shapesDS }"
It’s too bad that extensions don’t extend DependencyProperty but they don’t.
Just use IMarkupExtension instead of MarkupExtension and you can extend DependencyObject. At least in Silverlight 5 you can, but I would assume WPF also has it.

Resources