问题
I have my custom toolbar control with DependencyProperty IsBusy
Here is how I use it:
<Controls:myToolbar
Grid.ColumnSpan="5" Mode="DataEntry"
Status="{Binding State, Converter={StaticResource ViewEditingStateToToolbarStateConverter}}"
IsBusy="{Binding IsBusy}"/>
By convention all my VM's inherit from base VM and have IsBusy property. So, I KNOW that this property will always be available on VM.
Now I have another 4 properties like this. Instead of adding them to XAML on all my views I want to know how to bind to this IsBusy
automatically inside control's code so I don't have to bind in XAML?
EDIT
Actually, I found answer to my question: Silverlight: Programmatically binding control properties
Now, my question is:
Is it correct to apply this binding in constructor like this?
public myToolbar()
{
this.DefaultStyleKey = typeof(myToolbar);
var binding = new Binding("IsBusy") { Mode = BindingMode.TwoWay };
this.SetBinding(IsBusyProperty, binding);
}
Should I check if XAML binding (another binding) exist to this property and not bind? It works either way but I wonder if it's bad for performance, smells, etc?
What about doing this in onApplyTemplate
. Is that better way?
if (GetBindingExpression(IsBusyProperty) == null)
{
var binding = new Binding("IsBusy") { Mode = BindingMode.TwoWay };
this.SetBinding(IsBusyProperty, binding);
}
回答1:
It would be bad if you tried to use this control with a view model which doesn't have the IsBusy
property, but even then you'll receive just a debug warning in the output window, nothing to worry about.
As to the place of the binding, the constructor is appropriate if the dependency property which you are binding to doesn't perform any actions inside its callback.
But if the property changed callback tries to call such functions as GetTemplateChild
and retrieve inner controls - then you should move the binding to the OnApplyTemplate
functions, because only there you can be assured that inner controls exist.
By the way, if your dependency proeprty doesn't have a property changed callback and is used only in the control template like {TemplateBinding IsBusy}
, you can replace this line by {Binding IsBusy}
. Something like this, either by using binding or data triggers:
<ControlTemplate TargetType="{x:Type Controls:myToolbar}">
<Grid>
<ContentControl x:Name="content" ... />
<ProgressBar x:name="progress" ... />
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsBusy}" Value="True">
<Setter TargetName="progress" Property="Visibility" Value="Visible" />
</DataTrigger>
The idea is simple: TemplateBinding
is applied to dependency properties of the control, whereas Binding
is applied to properties of the DataContext object or the view model and they can coexist without problems.
来源:https://stackoverflow.com/questions/8854034/how-to-create-binding-inside-custom-control-automatically