When to use DataTrigger and when to use Converter? - wpf

Any Assumption or rule is there, when we can use DataTrigger and when we can use Converter?

DataTriggers are used to change styling depending on a specific value. For example change the TextBlock to red when its content is a number below 0.
Converter is used to convert a value to another type of value. For example to convert a boolean to a Visibility enum value

A DataTrigger can only be used to check for a specific value - it cannot e.g. check for ranges. A DataTrigger can be combined for multiple conditions (MultiTrigger) - a ValueConverter can only convert one value to another. (Of course, a MultiValueConverter can take many values (and listen for updates on all of them - but still only return one value.))
The two can be used in conjunction, though - say, having a ValueConverter that checks if the value is below 50 (returning true) to activate the DataTrigger (put it in the Binding of the DataTrigger).
So, there is no golden rule in my book - only circumstances that might make one of them unusable (or very, very hard to apply).

Related

WPF is it possible to temporarily change the Visibility Dependency Property of a DataGridColumn without destroying the original binding?

I have a WPFToolkit DataGrid with at least one column bound (via a proxy object as columns are not part of the visual tree) to a property. I wish to toggle all columns to Visible so that I can perform a calculation based on the DataGridColumnHeader (which is only created when its column is visible for the first time). Having done the calculation I want to reset the column to use the binding that was previously set.
I've attempted to get and store the Binding Expression etc, but with no joy. I have also attempted to use the DependencyObject.SetValue() method to change the property value non-destructively, but this doesn't event correctly change the value, let alone retain the original binding.
Any ideas?
You need to call SetCurrentValue() so that it won't clear the binding. SetValue destroys the old binding.
From MSDN:
This method is used by a component that programmatically sets the value of one of its own properties without disabling an application's declared use of the property. The SetCurrentValue method changes the effective value of the property, but existing triggers, data bindings, and styles will continue to work.
Given you have this
<TextBox Text="{Binding TestProperty}"/>
The SetValue you will overwrite the binding with whatever you provide. If you call SetCurrentValue, however, will ensure that the property takes on the given value, but won't destroy any bindings.
Be aware that you should not use SetCurrentValue in your dependency properties' setter/getter.
SetCurrentValue is more useful in scenarios where you need a property to take on a given value but don't want to overwrite any bindings, triggers, or styles that have been configured against your property.

How can I overrule/change and then reset a Binding?

I have a Canvas whose Width & Height are databound, e.g. Width:
Width="{Binding DrawingSize.Width, NotifyOnTargetUpdated=True}".
When I set the Canvas's Width somewhere in code behind to another value, the Binding is lost.
Can somebody explain why that is or where MSDN explains it?
MSDN explains this in the Dependency Property Value Precedence:
Dynamic resources and bindings have the precedence of where they were
set, but the value is deferred. One consequence of this is that if you
set a dynamic resource or binding to a local value, any change to the
local value replaces the dynamic resource or binding entirely.
You can use SetCurrentValue to change the current value without overriding anything. However, even if there are valid usages for this method, I personally wouldn't recommend it. You're likely to run into other problems such as "who set this value, that's not the one I expected", or "the binding has changed too early, I lost my current value". Consider using the coercion mechanism, described in the same MSDN page, instead.

Make use of ConverterParameter vs. using many converters

I have 2 different ProgressBars with 2 different custom styles. In each of them, Color of the ProgressBar is Calculated based on Maximum and Value (with 2 different formulas).
I see that the type of the ConverterParameter in a converter is String.
Now I'm wondering should I write 2 different MultiValueConverters for each of them, or write a single MultiValueConverter with a Parameter and let the Parameter decide which formula should be executed.
These 2 ProgressBars are probably the bottle-neck of my MVVM's View, so I need to know which one is better in performance?
Write one converter - it makes no sense to have multiple converters for the same purpose.
Indicate which formula you want to use by using an enumeration - the value can be explicitly mentioned in the XAML.
If you want to bind external values in to your converter it will need to derive from DependencyObject and the properties will have to be dependency properties.

Why does BooleanToVisibilityConverter seem to return "Hidden" (not "Collapsed") when passed DependencyProperty.UnsetValue?

I've made a simple viewer of XAML documents that use a number of our own value converters, as well as built in ones, of course. It is expected behavior that there are DependencyProperty.UnsetValue bindings present.
I'm encountering a problem where the resulting view of my document acts like the built-in BooleanToVisibilityConverter is returning "Hidden" in that situation. I had expected it to act as if false was the value passed in. I was not even aware that "Hidden" was a possible result, and no such thing is mentioned in the MS docs.
Since I don't want to be changing the documents themselves to suit, I'm not planning to make a converter of my own that behaves as I expect. Any ideas out there to get what I want here, or even confirmation that what I'm seeing makes sense?
The BooleanToVisibilityConverter returns a Visibility. If you consult the documentation, you will find that Hidden is a valid value. A binding that results in DependencyProperty.UnsetValue will not attempt to convert this value via its associated converter. It effectively turns off the binding, i.e. it should have the same result as if the binding was not present at all.
In this case, your Hidden value will be coming from elsewhere. To understand the mechanism for determining a dependency property value, look at the documentation regarding dependency property precedence. In your case, it is most likely an inherited, or default value (but that is just a guess!)

Silverlight DependencyProperty.SetCurrentValue Equivalent

I'm looking for a SL4 equivalent to .NET 4's SetCurrentValue API, which would appear to be exactly what I need for my scenario.
In short, I'm writing an attached behavior that updates the value of a given property at appropriate times. However, I don't want it to overwrite any bindings that are set on that dependency property. I merely want to push that value to the property (and therefore have any bindings refresh based on that value).
From what I can tell, there's no easy way to do this yet in SL4.
Thanks
Silverlight does not provide direct access to this level of dependency value. However its this level of value that Animations in storyboards set when they manipulate a property.
Hence a Storyboard with a 0 length duration containing a single DiscreteObjectKeyFrame might achieve your desired result.
I've managed to simulate what I'm after by detecting bindings and injecting a surrogate object between the source and target. I can then manipulate the surrogate and have both sides of the original binding refresh.
It's ugly and more work than I'd like, but it seems to work.
Kent

Resources