Is a separate WPF value converter object instantiated for each binding that a particular value converter class is used in?
I am trying to create a two-way bit-to-boolean value converter. I would like to be able to bind a bool property (such as IsChecked) to a bit in a value type (like a ushort). I'm using the converter's parameter arguments to specify the bit. Implementing the ConvertBack() method is easy, but Convert() is little trickier.
In Convert() I need to know what the value of the entire ushort is so I can toggle just the single bit I am interested in. I was thinking of just using a member variable in my value converter class to temporarily store this whenever ConvertBack() is called, thus leading to the above question: does each binding get its own value converter instance?
If you use a converter defined in your resources, it will be shared amongst your properties.
If you need unique converters:
If you create a specific converter for a property, however, it will not be shared. Either option is workable. You can even use multiple converters (of the same type, with different keys) in your resources, which will create unique instances.
Create a constructor and destructor in your converter and set breakpoints within to tell for sure. I just created a simple example and it looks like only one converter was created for my multiple viewmodels that were using the constructor
Related
I've seen both styles used in the same project, and I wonder if there's any semantic difference between them, or if any would be recommended over the other and why.
There is a significant difference here which you will run into as soon as you have a complex property path with typed parameters.
Conceptually they are equivalent as they both end up setting the Binding.Path, one via the parameterized Binding constructor, the other directly via the property. What happens internally is very different though as the Binding.Path is not just a string which in both cases would be passed on to the property, it is a PropertyPath.
When XAML is parsed, type converters are used to turn strings into the types expected by properties. So when you use Path= a PropertyPathConverter will be instantiated to parse the string and return a PropertyPath. Now here is the difference:
Binding(string path) invokes public PropertyPath(string, Object[])
PropertyPathConverter invokes internal PropertyPath(string, ITypeDescriptorContext)
(In the case of the Binding constructor the Object[] will be empty)
How does this matter?
If you for example have multiple indexers in a class e.g. one that expects a string and one that expects an int and you try to cast the value to target the latter, the cast will not work:
{Binding [(sys:Int32)0]}
The PropertyPath is lacking the ITypeDescriptorContext because the public constructor is invoked so the type System.Int32 cannot be resolved from the string sys:Int32.
If you use Path= however the type converter will be used instead and the type will be resolved using the context, so this will work:
{Binding Path=[(sys:Int32)0]}
(Aren't implementation details fun?)
They mean the same thing. Where they differ is in how the Binding object is instantiated and populated.
{Binding Path=Foo}
creates a Binding instance using its parameterless constructor, and then sets the instance's Path property.
{Binding Foo}
creates a Binding instance using its single-parameter constructor, and passes the value "Foo" to that constructor parameter. The single-parameter constructor just sets the Path property, which is why the two syntaxes are equivalent.
It's very much like the syntax for custom attributes, where you can also pass constructor parameters and/or set property values.
There is none.
When not specified, the Path property is assigned the value. In other words, Path is the default property of a binding.
It's like the "Content" property, which is the default property for many controls. For example
<Button>Hello</Button> Is the same as <Button><Button.Content><TextBlock Text="Hello"/></Button>
Hope that helps.
There is no semantic difference, the first property in the binding will be interpreted as the "Path" property if no property name is supplied.
It's a matter of coding style.
Update
Removed the sentence "It is the default property".
I realize that there is no formal support for "default properties", but the scenario is often referred to as the "default property", and is supported by convention.
Example, from the MSDN documentation for the Path property of the Binding markup extension:
The Binding markup extension uses Binding.Path as a conceptual "default property", where Path= does not need to appear in the expression.
I do not think I am wrong and completely misguided to use this terminology as is being suggested. I also understand how it is implemented.
Don't think there's any difference, expect perhaps the second is more explicit.
I'm a little bit unclear with all this magic.
As I understood dependency properties get inherited from the DependencyObject, so values are stored:
in the instance itself if value is assigned (in the local dictionary)
or taken from the link to a parent element if value is not specified.
protected object GetValue(string propertyName)
{
if (LocalValues.ContainsKey(propertyName))
{
return LocalValues[propertyName];
}
return Parent.GetValue(propertyName);
}
Am I correct in this?
I also don't understand where are values for attached properties stored?
Control.FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
typeof(Control), new FrameworkPropertyMetadata(SystemFonts.MessageFontSize,
FrameworkPropertyMetadataOptions.Inherits));
Does AddOwner method call on Attached property assigns value to the instance field? When does this happen and where does the value go?
Thanks!
Values for dependency properties are stored inside the objects (derived from DependencyObject) which we apply a property value to.
Let's take your TextElement.FontSizeProperty attached property for example:
<StackPanel TextElement.FontSize="20" ... >
...
</StackPanel>
XAML parser translates it to the following:
...
TextElement.SetFontSize(stackPanel, 20);
...
which is internally:
public static void SetFontSize(DependencyObject element, double value)
{
element.SetValue(TextElement.FontSizeProperty, value);
}
So, setting TextElement.FontSize on a stackPanel object is the same as calling
stackPanel.SetValue(TextElement.FontSizeProperty, value)
SetValue() is a method defined in the DependencyObject class. Inside the method many complex things happen, but in the end the effective value of a dependency property is wrapped in a structure called EffectiveValueEntry and stored in the following instance field inside DependencyObject:
private EffectiveValueEntry[] _effectiveValues;
The property system in WPF is pretty complex. MSDN really has a lot of information, but it is often hard to find. While there are many ways a DependencyProperty can be set, I'm not sure that you need to care where the values are stored.
For local values, you can assume that it is stored on the DependencyObject (again you shouldn't care where it is stored), with the caveat that they are not stored based on strings. It truly is associated with an instance of DependencyProperty. This is why you would want to add an owner to the property. If somebody sets TextElement.FontSize on your control, it is just like setting your local FontSize property.
As far as inheriting values for a property from a parent, this only happens with attached properties. From the MSDN entry for FrameworkPropertyMetadataOptions:
Although property value inheritance might appear to work for
nonattached dependency properties, the inheritance behavior for a
nonattached property through certain element boundaries in the runtime
tree is undefined. Always use RegisterAttached to register properties
where you specify Inherits in the metadata.
I am not sure that I fully understand the advantage of binding. For example, if I want to bind a string value to a TextBlock I need to do the following:
Create a class that extends INotifyPropertyChanged
Add a string to that class (say: MyString)
Extend the set method for MyString so that it calls another method (say: OnPropertyChanged)
Create the OnPropertyChanged method to call the PropertyChangedEventHandler event
Then I need to create a new instance of the class, set my TextBlock.DataContext to point to that class, and finally add the XAML bit for the binding.
Can someone explain the advantage of this over simply setting:
TextBlock.Text = MyString;
Thanks!
Any changes to MyString won't be automatically reflected in your UI.
Your code behind will be littered with "when this event occurs, update these pieces of data", so you'll essentially be writing your own messy data binding logic for each and every view.
The advantage is that you can both change and display the value in multiple places, without having to update some method to add another TextBlock assignment each time the value changes. Any new display control just binds itself to the property, the rest is automatic.
Now if you really just set the value in one place and show it in one control, then you're right, there's not much point.
The gain of using Data Binding isn't particularly noticeable for a TextBlock binding to a static string.
However if the value of MyString changes during application runtime it becomes much more useful - especially in a case where the object that owns that property is unaware of the TextBlock. This separation between UI and the underlying data layer can be created using a design pattern such as MVVM.
Data Binding is also useful for more complex properties such as Items in a ListBox control. Just bind the ListBox.Items to a property that is of type ObservableCollection and the UI will automatically update whenever the content of that collection changes.
Since UserControls in WPF have to have parameterless constructors, what is the correct way for supplying them with fairly complex data that is needed "near" the time of construction. I have tried using dependency properties for this, but am running into issues with the Visual Studio designer balking at attempts to pass stuff like a Dictionary<string,MyObject> into an IDictionary<string,MyObject> typed dependency property. At some point it must want an exact compile time type match, or the XAML doesn't come up in the designer, although the application executes just fine.
Basically, I want a good way to pass in stuff that I would normally pass into a constructor into a User Control. What's the best way?
Update:
The user control in question will always be created from XAML, so having a non-parameterless construction in addition to the parameterless one is not an option.
Update 2:
An interesting idea would be to have something accessible from the parameterless constructor that I can get my initialization data from. Something like perhaps asking the question: Which of my already initialized ancestors implements an IMyDataProvider interface? This could be similar to how the relative source to ancestor type bindings work, except done programatically from the user control constructor.
If the only problem you are having is passing in derived types, you can pass in instead a simple concrete container class containing your complex types as properties. For example:
public class InitializationData
{
public IDictionary<TKey, TValue> Dictionary { get; set; }
}
This level of indirection will overcome the limitations of the Visual Studio designer.
A couple of options.
1, You can have more than one constructor, a parameterless one for when your control is created via XAML and another that takes a set of parameters for when you create it directly via code. If you definitely don't want to create your instance via code then...
2, Add a public property that only has a setter and is defined with the exact dictionary type you want to pass in and use as the data for initializing the control. The property only needs to be called once. You can have other properties that are getters/setters that expose that initialized data in order more generic types.
Is there a way to know the first time a Dependency Property is accessed through XAML binding so I can actually "render" the value of the property when needed?
I have an object (class derived from Control) that has several PointCollection Dependency Properties that may contain 100's or 1000's of points. Each property may arrange the points differently for use in different types shapes (Polyline, Polygon, etc - its more complicated then this, but you get the idea). Via a Template different XAML objects use TemplateBinding to access these properties. Since my object uses a Template I never know what XAML shapes may be in use for my object - so I never know what Properties they may or may not bind to. I'd like to only fill-in these PointCollections when they are actually needed.
Normally in .NET I'd but some logic in the Property's getter, but these are bypassed by XAML data binding.
I need a WPF AND Silverlight compatible solution.
I'd love a solution that avoids any additional complexities for the users of my object.
Update
One way that I've found to do this is using Value Converters. In my situation I had multiple point collections. There was a main dep. property that contained the usual shape of the data. Two alternate shapes were needed for reuse in other areas/contexts.
At first I had 3 dep. props. But, I could have just had one property (the usual shape) and used a value converted to transform the points into my other 2 desired shapes. Doing this I only make the one set of points in the control. The expense of transforming points to the secondary shapes is only incurred when used. Now my main control doesn't need to anticipate how data needs to look for every possible template thrown at the control - now its the template designers problem.
Update 2
Certainly INotifyPropertyChanged and regular properties are the recommended way to handle this.
You don't necessarily have to use dependency properties to enable data-binding. However, you then have to implement INotifyPropertyChanged if changes at the source should be propagated to the target of the binding. A "normal" .NET property is easy to lazy load perhaps like this:
PointCollection points
public PointCollection Points {
get {
return this.points ?? (this.points = CreatePoints());
}
}
PointCollection CreatePoints() {
// ...
}
I'm not sure how you can fit INotifyPropertyChanged into your control, but it sounds a bit strange that your control supplies data to other parts of the system. Perhaps you need to create a view-model containing the data that you then can let your control data-bind to.
If I paraphrase your question to
How do I get notified when dependency property is changed?
will this be correct? I draw this from your phrase "Normally in .NET I'd but some logic in the Property's getter, but these are bypassed by XAML data binding".
If I'm correct, then you can register your own property changed callback. It's always called. Doesn't matter who caused the change binding, style or trigger. The following code snippet is taken from MSDN Article "Dependency Property Callbacks and Validation":
public static readonly DependencyProperty CurrentReadingProperty =
DependencyProperty.Register(
"CurrentReading",
typeof(double),
typeof(Gauge),
new FrameworkPropertyMetadata(
Double.NaN,
FrameworkPropertyMetadataOptions.AffectsMeasure,
new PropertyChangedCallback(OnCurrentReadingChanged),
new CoerceValueCallback(CoerceCurrentReading)
),
new ValidateValueCallback(IsValidReading)
);
public double CurrentReading
{
get { return (double)GetValue(CurrentReadingProperty); }
set { SetValue(CurrentReadingProperty, value); }
}
Your takeaway here is OnCurrentReadingChanged() method. Hope this helps :).