WPF UserControl pre-configuration - c#

I'm designing an user control and I'd like to make its behaviour configurable - but just once, when it's created. I don't need it to adapt later on, since I know beforehand that a specific window will to use it with a specific configuration.
Consider this simple markup:
<MyControl SomeProperty="True" SomeOtherProperty="12345" />
SomeProperty and SomeOtherProperty are DependencyProperties declared in my codebehind.
The issue is: The control does some preprocessing of its input data in its constructor, before InitializeComponent() is called. On that stage, I don't have the access to SomeProperty or SomeOtherProperty defined by the user - they still have the default values.
After that, if these properties are set in the XAML, they're assigned the values after the constructor. I can respond to them by introducing a PropertyChangedCallback and performing the calculations over again after each property is updated.
This is sub-optimal since I just want to pass the values once and make sure that the control's initialization logic is only ran once too - already with correct settings. The solution with PropertyChangedCallbacks requires me to make this control more complex, i.e. responsive to any changes to these dependency properties during the control's whole lifetime. This is much more than I need - it would be satisfactory for my properties to be read-only and set only once at the moment of control creation.
How can I manage to do that while keeping the XAML markup clean?

Your control must be constructed in order for WPF to set the properties - there is no way to "delay" the construction until after the properties are set.
Instead of putting your initialization logic in the constructor, you might want to try putting it elsewhere, such as subscribing to the Loaded event and initializing there. This will happen after the properties are set.

Related

Where initialize a specialized wpf control?

Let's say that I want create a specialized wpf control, "YellowTextBox". It will be the same of a common TextBox, but it will be... yellow!. Ok, I go to code:
public class YellowTextBox: TextBox
{
}
Now, the obvious part, I want it be yellow...
this.Background = Brushes.Yellow;
Where I put that line of code? In the constructor? In OnInitialized override? OnLoaded, etc...
There are some correct (or better) place to put that line of code?
EDIT:
I know I can do it via styles, my question is more an "OOP" way of do it, it can be any other kind of property or field, not exactly Background Color, that selected property was just an example :/
You really ought to initialize a specialized WPF control in the initializers for the dependency properties (for properties it introduces), and in the default Style (for the new properties, and for anything it inherits that needs a different default value).
But you want to do it in C#, for some reason.
In that case, we're talking about a) OOP theology, b) OOP reality, and C) WPF mechanics. In terms of all of those, do it in the constructor, and in WPF, in the constructor after InitializeComponent() (if applicable, not in your case) is called. That'll precede any styles that get applied to the control in WPF, and it's good OOP practice and theology to initialize everything in the constructor that you didn't initialize in field initializers. A new instance of a class should be ready to go, in a consistent state that won't throw any exceptions if you start using it. So that means the initialization should be all complete at that point. Never leave any initialization to anybody else. That's a booby trap.
Do read up on InitializeComponent(), but in your specific case, the constructor for a subclass of a standard control, you won't be calling it.
A control subclass in WPF will apply styles after the constructor. It must! Before the constructor executes, it doesn't exist. "After the constructor" is basically all there is, aside from the guts of the constructor itself. You can override OnApplyTemplate() to hook into things immediately after the template is applied. But that's much too late to be initializing much (with the exception of private fields which will refer to template children).
So if you initialize stuff in the constructor(s), it gets applied to every instance, and if it's a WPF control class (or any FrameworkElement subclass), consumers of your class can override it by applying a Style or a template later on. That's good WPF practice: You want to allow people maximum scope to customize your controls.

When should I use dependency properties in WPF?

When should I use dependency properties in WPF?
They are static, so we save a lot on memory, compared to using .NET properties.
Other gains of using dependency properties over .NET properties are:
1) no need to check thread access
2) prompt a containing element to be rendered
etc...
So it seems I should ALWAYS use dependency properties in my projects where I use WPF?
Maybe for some trivial properties of helper classes here and there I could
get away with .NET properties...
Dependency Property is a broad concept to explain which might take couple of pages to write. So just to answer your main question, Dependency property is used where
You know the property is going to be the binding target i.e you are creating a user control/custom control and want property that should be binding driven.
You want automatic property change notifications (coerse and validation also).
We want value inheritance in styles,themes, parent or default value.
There is not need to create the properties on Model or ViewModel layer as dependency properties most of the time as that is not going to help much on memory saving front as most of the properties we define in model/VM will have values per instance as they will be constantly changing. Resolving Dependency property value is a burden in itself so making property dependency unnecessarily is not advisable.
Thanks
The main reason to create DependencyProperty is when you write you own WPF control.
DependencyProperties can be used as binding source and target, and can be animated.
The properties of all framework's controls are implemented as DependencyProperty, that why you can make powerful data binding in XAML.
However in most situation, like in with the MVVM pattern, you don't need dependency properties, INotifyPropertyChanged is enough.
The main difference is, that the value of a normal .NET property is read directly from a private member in your class, whereas the value of a DependencyProperty is resolved dynamically when calling the GetValue() method that is inherited from DependencyObject.
When you set a value of a dependency property it is not stored in a field of your object, but in a dictionary of keys and values provided by the base class DependencyObject. The key of an entry is the name of the property and the value is the value you want to set.
The advantages of dependency properties are
Reduced memory footprint:
It's a huge dissipation to store a field for each property when you think that over 90% of the properties of a UI control typically stay at its initial values. Dependency properties solve these problems by only store modified properties in the instance. The default values are stored once within the dependency property.
Value inheritance:
When you access a dependency property the value is resolved by using a value resolution strategy. If no local value is set, the dependency property navigates up the logical tree until it finds a value. When you set the FontSize on the root element it applies to all textblocks below except you override the value.
Change notification:
Dependency properties have a built-in change notification mechanism. By registering a callback in the property metadata you get notified, when the value of the property has been changed. This is also used by the databinding.
check the below url for more details about the magic behid it
dependency properties in WPF
CLR Property vs. Dependency Property
A CLR property reads directly from the private member of the class. The Get() and Set() methods of the class retrieve and store the values of the property.
Whereas when you set a value of a Dependency Property it is not stored in a field of your object, but in a dictionary of keys and values provided by the base class DependencyObject. The key of an entry is the name of the property and the value is the value you want to set.
Advantages of a Dependency Property
Less memory consumption
The Dependency Property stores the property only when it is altered or modified. Hence a huge amount of memory for fields are free.
Property value inheritance
It means that if no value is set for the property then it will return to the inheritance tree up to where it gets the value.
Change notification and Data Bindings
Whenever a property changes its value it provides notification in the Dependency Property using INotifyPropertyChange and also helps in data binding.
Participation in animation, styles and templates
A Dependency Property can animate, set styles using style setters and even provide templates for the control.
CallBacks
Whenever a property is changed you can have a callback invoked.
Resources
You can define a Resource for the definition of a Dependency Property in XAML.
Overriding Metadata
You can define certain behaviours of a Dependency Property using PropertyMetaData. Thus, overriding a metadata from a derived property will not require you to redefine or re-implement the entire property definition.
Perhaps you should take another look at the Dependency Properties Overview page at MSDN.
Personally, I would only ever create a DependencyProperty when I really need to. For the most part, I use normal CLR properties in data type and view model classes to bind to... this is absolutely fine, as long as I implement the INotifyPropertyChanged interface.
So for all of my usual data bindings, I use normal CLR properties. I only declare a Dependency Property in order to provide some added functionality in a UserControl.
Dependency properties are used when you want data binding in a UserControl, and is the standard method of data binding for the WPF Framework controls. DPs have slightly better binding performance, and everything is provided to you when inside a UserControl to implement them.
Otherwise, you typically use INotifyPropertyChanged for binding elsewhere, since it's easier to implement in stand-alone classes and has less overhead. As far as your original assumptions:
There is a local instance of your variable, you definitely do not save any overhead over a property since there is significant data binding logic built-in.
They must be accessed on the main thread.

Can I prevent SharpDevelop design view from setting a property's value in InitializeComponent?

I am finding that Design View (DV) is nice, but trying to change the way it automagically injects code into InitializeComponent is very hard. And sometimes its automagical code breaks the program.
For example, DV automatically sees every single property of my custom UserControl, and then it assigns every single property to some value in InitializeComponent. But I don't want it to assign values to some of the properties because some of my setters will throw a runtime exception if not used correctly. I could correct InitializeComponent manually, but anytime I make a change to the design, SharpDevelop will just regenerate the function again.
And there's another case where I have the Default Constructor set the size based upon certain factors, but then InitializeComponent will immediately set it to another static value.
How can I tell DV to not automagically assign values to certain properties I define?
Unless I misunderstood your scenario, it seems like you're barking up the wrong tree by trying to modify or reconfigure SharpDevelop's behavior. Even if you manage to change it, you won't affect Visual Studio's behavior, and you won't help any of the other consumers of your custom control who don't happen to (and/or don't want to) configure their designer accordingly.
Instead, it seems that you should just mark the properties exposed by your custom control with the [DesignerSerializationVisibility] attribute. This indicates to the designer exactly how that property's value should be serialized into the InitializeComponent method.
You have a choice of three different values:
Visible indicates that the value for the property should be persisted in initialization code
Hidden indicates that the value for the property should not be persisted in initialization code
Content indicates that initialization code should be generated for each public (not hidden) property of the object assigned to the property
The default value is Visible, which causes a property's value to be serialized whenever possible.

Need a short and clear definition for "Dependency Properties"

I'm trying to figure out what exactly Dependency Properties are, but when I look anywhere for a definition, I only find "how to use" but not "what it is".
Imagine you are asked on a job interview - what is a dependency property. What would be your answer?
A DependencyProperty is a property whose value depends (or can depend) on some other source (such as animation, data binding, styles, or visual tree inheritance). A regular property's value is stored in the object it belongs to, while you can think of a dependency property as being stored in a database somewhere. This database is essentially composed of a dictionary that maps (object, property) pairs to their values, along with a mapping of which properties depend on other properties (e.g. so when you change the DataContext of a Panel, it can notify all the children inside the panel).
So why do they store property values in some magic database somewhere? There are a few reasons:
It reduces storage space. Adding a property (even if its value is null) to a class adds 4 bytes (8 for a 64-bit process) of space to every instance of the class. A DependencyProperty only takes up space when an instance has a value. For example, a FrameworkElement has dozens of dependency properties, most of which are never assigned values. If all those properties were stored in the class, each instance would be hundreds of bytes. Instead each instance is only about 40 bytes.
It enables attached properties. Properties like Canvas.Left and Grid.Row have to be stored on objects that have never heard of a Canvas or Grid, so where do you put them? You put them in a database somewhere.
It enables automatic property changes. Imagine how you would implement something like styles or property inheritance (the ability to set something like a font or data context on a parent element and have its value propagate to all child elements). Having all of this stored in a database makes it so the code is all in one place instead of being implemented separately for each object and property that needs it.
"gives you a bunch of infrastructure to do all the things that you often want to do with a normal property - validate it, coerce it into a proper range, give out change notifications, and a number of other aspects."
WPF Tutorial - Introduction To Dependency Properties
A dependency property is a property that is backed by the WPF property system instead of by a field in the declaring class.
The significance of this is that, because WPF owns the property, WPF can factor in various considerations when calculating the property value -- such as animations, styles and data bindings. Another consequence is that because properties are managed by WPF they don't have to be declared on the classes that conceptually have the state: hence, atttached properties, which allow e.g. a Grid to associate Grid-specific state with non-Grid objects.
(By the way, I've mentioned WPF above because this is the main framework that uses DPs, but Windows Workflow Foundation also has the notion of dependency properties. So to be strictly correct a DP is a property that is backed by an external property system, specifically one which allows factors other than "the last set value" to come into play when getting the property value.)
MSDN provides a good definition, description and examples
For more deep understanding of DependencyProperty check here
A dependency property depends on multiple providers for determining its value at any point in time. These providers could be an animation continuously changing its value, a parent element whose property value propagates down to its children, and so on.
Arguably the biggest feature of a dependency property is its built-in ability to provide change notification.
Whenever the value of a dependency property changes, WPF can automatically trigger a number of actions, depending on the property’s metadata. These actions can be re-render-
ing the appropriate elements, updating the current layout, refreshing data bindings, and
much more. One of the most interesting features enabled by this built-in change notifica-
tion is property triggers, which enable you to perform your own custom actions when a
property value changes, without writing any procedural code

WPF - Dynamic tooltip

I have a class ToolTipProvider
which has a method
string GetToolTip(UIElement element)
which will return a specific tooltip for the UIElement specified, based on various factors including properties of the UIElement itself and also looking up into documentation which can be changed dynamically. It will also probably run in a thread so when the form first fires up the tooltips will be something like the visual studio 'Document cache is still being constructed', then populated in the background.
I want to allow this to be used in any wpf form with the minimum effort for the developer. Essentially I want to insert an ObjectDataProvider resource into the Window.Resources to wrap my ToolTipProvider object, then I think I need to create a tooltip (called e.g. MyToolTipProvider) in the resources which references that ObjectDataProvider, then on any element which requires this tooltip functionality it would just be a case of ToolTip="{StaticResource MyToolTipProvider}"
however I can't work out a) how to bind the actual elemnt itself to the MethodParameters of the objectdataprovider, or b) how to force it to call the method each time the tooltip is opened.
Any ideas/pointers on the general pattern I need? Not looking for complete solution, just any ideas from those more experienced
Create a new user control which functions as a tool-tip view factory.
Use your control as the tool-tip, passing any data you need for the factory to your control using binding (e.g. the data, the containing control, ...)
<AnyControl>
<AnyControl.ToolTip>
<YourToolTipControl Content="{Binding}" />
</AnyControl.ToolTip>
</AnyControl>
Not calling myself an expert, but I'd probably attempt such a feature with an attached property. This would be attachable to any element in your UI and you can specify an event handler that gets access to the object to which the property is being attached as well as the value passed to the attached property. You can keep a reference to the element to which your attached property was attached and you would then be able to change the ToolTip whenever you want.

Categories