Use MarkupExtension in PriorityBinding - wpf

EDIT: TL/DR
You can use custom markup extensions in PriorityBinding. It likely gets highlighted with an error message and the designer might not show it at design time but it works like a charm at runtime. Seems to be an issue with the XAML designer or some other internal component.
Well I have certain scenarios in our software where I need to display a translated string in case the binding returns null. Here my production number is set only at a certain point and until then I want to show "Unknown" translated in the user's language. For this we're using a custom markup which returns a binding to an intermediate object that supports translation.
Sadly MarkupExtension is inherited by BindingBase and not the other way around. So since PriorityBinding expects a collection of BindingBase I can't add my translation markup as fallback binding.
This is what I tried:
<PriorityBinding>
<Binding Path="ProductionNumber" />
<l:Translate Key="Unknown" Context="Common" />
</PriorityBinding>
So does anyone know how to work around this? Using PriorityBinding would be the easiest way to do this. Of course I could use a converter for this but then I would eliminate some essential features implemented in the markup which basically renders it useless.

Related

Is there a concise way of applying Binding.ValidationRules in XAML

I'm working on the validation rules for some data input forms in WPF/XAML. I've been able to get the user experience I would like, by explicitly applying validation rules to the field bindings:
<Binding
Path="qtyoffset"
NotifyOnValidationError="True"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="PropertyChanged"
>
<Binding.ValidationRules>
<utility:DecimalValidationRule precision="1" />
</Binding.ValidationRules>
</Binding>
With the above, the field is validated on every key press. If the user enters a 'X', the field is immediately flagged as invalid, the error message shows up in the appropriate place, the "commit" button is immediately disabled, etc. All nice and slick. Same thing happens if the user enters two digits after the decimal point, enters two decimal points, etc.
My only problem is the verbosity. The above binding code needs to be provided for every field, and if it's not quite right on one field, that one field will work not quite right. I'd much rather specify only the binding path, and have the rest of it added automatically. Set NotifyOnValidationError, ValidatesOnDataErrors, and UpdateSourceTrigger on every binding, set whichever validation rules are appropriate for the specific data type, depending on the type it is bound to. Or, at least, according to the type I specify in XAML.
I'm thinking about the way I would do validation in JQuery. Rather than statically listing all the validation rules on each input element, I'd set a number of classes. And then, on load, I'd use JQuery's DOM search capabilities to find every input element with a specific class set, and dynamically add the appropriate validation functionality.
XAML provides a very nice way of providing this sort of concise configuration for display elements, using Styles and Setters. But that doesn't work for Bindings.
Is there a reasonable alternative?
Short answer: No, not really.
However you can do 2 things:
You can put
NotifyOnValidationError="True"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="PropertyChanged"
in resources and access them as StaticResource, to factor out redundant information, and then you could change all of those properties in one place.
You can make your own markup extension based on Binding. That would make a much shorter XAML declaration. And you could use it like: <TextBox Text={local:DecimalBinding Path=qtyoffset} />
HTH,
Bab.
This would probably be overkill for your needs, but one thing you could do is to subclass the WPF UserControl, and then write a function when the UserControl is loaded and also when new bindings are applied, that walks down the visual tree looking for Bindings of the relevant types and applies the validation to them.

Approach for a multi-lingual WPF application

it seems there are a number of approaches on how to implement multiple languages in a WPF application. But I would like some more information about what method I should be using with the following requirements:
It's a PRISM application, so a number of independent modules (assemblies) working together. I would like that each assembly has its own translations of UI elements.
I need a simple approach, no tools needed to generate stuff
Should still be able to use blend to design the UI
Optionally be able to switch language without restarting the application (not a dealbreaker)
Can someone advice me on how to achieve this?
Thanks!
A common approach is to bind the text property of your textblocks / labels etc.. to some property on a statically defined localization resource:
<Label Content="{Binding Source={x:Static loc:LanguageContext.Instance},
Path=Dictionary, Mode=OneWay,
Converter={StaticResource languageConverter},
ConverterParameter=TextId}" />
i.e. LanguageContext.Instance exposes a dictionary via a property Dictionary, the Converter uses the given ConverterParameter to look up the text identified via TextId.
This is a cumbersome approach, and will not fulfil all your requirements.
A better method is to defined your own markup extension to perform this sort of logic. There are a couple of solutions I have seen on the web, this high rated codeproject article:
http://www.codeproject.com/KB/WPF/realtime_multilingual.aspx
And a similar solution here that provides Blend, on-the-fly language changes, so is probably a good choice for you:
http://blogs.microsoft.co.il/blogs/tomershamam/archive/2007/10/30/wpf-localization-on-the-fly-language-selection.aspx
With the above example you define an attached property which identifies the key of the translated item, and use the Translate markup extension to identify the properties which are translated.
NOTE: it is not just text which is being translated here, often you have to change colors / graphics etc ...
Meanwhile I found an open source project that works really well: http://wpflocalizeextension.codeplex.com. It's just adding a reference to the dll, adding the resources with translations, and using it in XAML. It worked in 5 minutes. I can add multiple resources to individual modules; and it works fine in visual studio designer and blend. And, locale can be changed on the fly. Meets my requirements :)

Where should I set the DataContext - code behind or xaml?

(honestly I searched and read all the 'related questions' that seemed relevant - i do hope i didn't "miss" this question from elsewhere but here goes...)
There are two different ways (at least) to set the DataContext. One can use XAML or one can use the code behind.
What is the 'best practice' and why?
I tend to favor setting it in XAML because it allows a designer to define collections on their own but I need 'ammunition' on why it's a best practice or why I'm crazy and the code behind is the bomb...
A third way you might look at is using a locator service. I usually have one class that is responsible for the creation of all my DataContext(VM's in most cases for me) and I create an instance of that class in the App.xaml Resources. Then I bind the DataContext in the XAML of each individual page.
i.e.
<Page DataContext="{Binding ViewModel,Source={StaticResource Locator}}" >
I think it depends on what you are setting the DataContext to, and ultimately personal preference.
I personally always do it in the code behind of my views because I find it overall cleaner, and it was how I was taught MVVM. Another thing to keep in mind is, there are times you may need to change your datacontext depending on what you are working with. If this is the case it's much cleaner/easier to do in the code behind rather than in XAML.
As you can see by the answers so far opinion is divided. In truth there is no best practice (I do get bee in my bonet about discusions of "best practice" in the Silverlight world, its way too young for best practice to be truely known.)
The reality actually is that you can't set the "data context" in Xaml. Unless you actually construct an object instance like this:-
<UserControl>
<UserControl.DataContext>
<local:MyDataProviderThing />
Ultimately something external has to assign either the DataContext property directly or indirectly via another property or via binding (as in Stephan's answer). Its this external context which is dictates whether it makes sense to do it in Xaml or not. Many MVVM solutions use a binding in Xaml, in some cases simply to avoid there having to be any code at all in code-behind rather than it truely being "better". Others set up the DataContext in code using a base class that your control derives from.
DataContext of the user control/view I assume? One advantage of setting data context in the code behind is the availability of dependency injection. Your DI container can take care of any dependencies for you dynamically at run-time.
With this pattern, I frequently set a view's Blend design DataContext in xaml using d:DataContext. The "design version" can provide mock data for use in Blend, while the true implementation is resolved at run-time.

Modify XAML string dynamically

I want to add/remove some part of XAML dynamically i.e. from code behind file in C#.how to Add any specific XAML string on specified location (means under some tag) from .cs file. Please help.
XAML is xml you can use XmlReader and XmlWriter or any other of the XML serialization mechanismn of .NET to write/read XML (XMlDocument is probably the best approach here to modify existing xml). ALso there are the XamlReader and XamlWriter class that allow ou to (de)serialize any object graph from/to XAML automatically. If you can use .NET 4.0, you have even more fine grained possibilities to athor XAML because it has a new XAML stack. Use this as a starting point.
What is it that modifying the XAML will do for you?
If you just want to change the appearance of your WPF application (perhaps by adding some more content at certain locations), it will most likely be easier to do this by referencing the objects in question. So, if you need to add some text to a button, name the button with x:Name="myButton" and in code set: myButton.Content = "Click Me"
XAML is really a technology for constructing object hierarchies. Pretty much every element in the XAML corresponds to a .NET CLR class. When loaded, these classes are instantiated nd populated according to the attributes used in the XAML. Once loaded, the XAML has finished it's job and is essentially unloaded/unavailable.
You might need to do something beyond this, but from your brief question it doesn't seem like it. I would just work on the object model and leave the XAML be.

Is there a way to follow a binding in code?

If i have a Binding which has a property path and the data source can i execute it in code, to find the value?
The path that i am trying to follow can be quite complicated, including collection lookup and multiple levels.
there is a hack :
create a content control
use BindingOperations.SetBinding()
then retrieve the content
is there a better way?
You can avoid using a ContentControl, and write your own very simple class that derives directly from DependencyObject, and provides a single DependencyProperty, which you can then target with the binding. Aside from that, no, there isn't any better way - binding machinery in WPF is very much tied into the concept of dependency properties, and a binding cannot really be a "free-standing expression" that is just evaluated.

Resources