While using WPF I noticed that when I add a control to a XAML file, the default constructor is called.
Is there a way to call a parameterized constructor?
While using WPF I noticed that when I add a control to a XAML file, the default constructor is called.
Is there a way to call a parameterized constructor?
.NET 4.0 brings a new feature that challenges the answer - but apparently only for UWP applications (not WPF).
<object ...>
<x:Arguments>
oneOrMoreObjectElements
</x:Arguments>
</object>
One of the guiding principles of XAML-friendly objects is that they should be completely usable with a default constructor, i.e., there is no behavior that is only accessible when using a non-default constructor. To fit with the declarative nature of XAML, object parameters are specified via property setters. There is also a convention that says that the order in which properties are set in XAML should not be important.
You may, however, have some special considerations that are important to your implementation but at odds with convention:
StreamSource
and UriSource
of an image.To make it easier to handle these cases, the ISupportInitialize
interface is provided. When an object is read and created from XAML (i.e., parsed), objects implementing ISupportInitialize
will be handled specially:
BeginInit()
will be called.EndInit()
is called.By tracking calls to BeginInit()
and EndInit()
, you can handle whatever rules you need to impose, including the requirement that certain properties be set. This is how you should handle creation parameters; not by requiring constructor arguments.
Note that ISupportInitializeNotification
is also provided, which extends the above interface by adding an IsInitialized
property and Initialized
event. I recommend using the extended version.
Yes, you can do it by the ObjectDataProvider
. It allows you to call non-default constructor, for example:
<Grid>
<Grid.Resources>
<ObjectDataProvider x:Key="myDataSource"
ObjectType="{x:Type local:Person}">
<ObjectDataProvider.ConstructorParameters>
<system:String>Joe</system:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</Grid.Resources>
<Label Content="{Binding Source={StaticResource myDataSource}, Path=Name}"></Label>
</Grid>
assuming that Person is
public class Person
{
public Person(string Name)
{
this.Name = Name;
}
public string Name { get; set; }
}
Unfortunately, you cannot bind the ConstructorParameters
. See some workaround here.