很多控件公开属性不DependencyProperties,那么你不能把它有约束力的。在另一些情况下,你只为存取的getter,你不能把它有约束力吗??
这是色带组办公室带状或转换器的参数的情况下,例如。
如果你试图这样做,你一定有一个抛出的异常:
一个"结合",不能设置"SetCEDEJDED"类型"Tralala"属性。
A"结合",只能设置DependencyObject的DependencyProperty的。
在这篇文章中,我们会发现一个变通??/ P>
其主要思想是使用代理/观察员(),这将反映源对象上的每一个变化的目标对象,反之亦然。
这里是解决方案的主要部分。产品规格:我们将使用的XAML代码
下面的代码片段,它描述了我们将如何在XAML中使用我们的代理。有没有代码隐藏。
我们的代理/观察员正确的基类<Window x:Class="BindOnNonDependencyProperty.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:us="clr-namespace:BindOnNonDependencyProperty"
Title="BindOnNonDependencyProperty" >
<DockPanel >
<TextBox x:Name="myTextBox" DockPanel.Dock="Top" />
<TextBox x:Name="monTextBlockCible" DockPanel.Dock="Top" />
<us:ExtendedBinding Source="{Binding ElementName=myTextBox,Path=Text,Mode=TwoWay}"
Target="{Binding ElementName=monTextBlockCible,Path=Text,Mode=TwoWay}"
/>
</DockPanel>
</Window>
我们将其称之为ExtendedBinding,它必须从DependencyObject继承最后能够把自己的DependencyProperty。但是,只有这样,才能加入到我们的XAML的DependencyObject的是添加到resourceDictonary。
这是一个缺点,因为这样做,它将不再在控件树,然后将不可能就其属性之一具有约束力。请注意,仍然可以使用它作为一个从我们的XAML中的另一个地方目标,但你不能这样做,其属性之一绑定。此代码将无法正常工作:{C}
然后把内部控制的树,我们只有使UIElement的,你会说... ...没有,因为在实际版本的框架,你不会有继承DataContext的,将被禁止使用"的ElementName"具有约束力的。希望有一个解决方案,我们的代理要继承自FrameworkElement,一切都将正常工作!该DependencyProperties
我们将添加两个dependencyProperties,将目标和第二个源。
这些DPS将定制使用的FrameworkPropertyMetadata启用这些功能:绑定将使用TwoWay的模式UpdateSourceTrigger用于将PropertyChanged事件它如何工作
我们代理的核心是覆盖DependencyObject的OnPropertyChanged方法。每个源或目标上的变化将更新其对应。
我们要小心,不要陷入循环:当我们将更新的目标或源,我们也将提高一个PropertyChanged事件,我们必须忽略这一个... ...最终的代码
{A}public class ExtendedBinding : FrameworkElement
{
#region Source DP
//We don't know what will be the Source/target type so we keep 'object'.
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(object), typeof(ExtendedBinding),
new FrameworkPropertyMetadata()
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
});
public Object Source
{
get { return GetValue(ExtendedBinding.SourceProperty); }
set { SetValue(ExtendedBinding.SourceProperty, value); }
}
#endregion
#region Target DP
//We don't know what will be the Source/target type so we keep 'object'.
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register("Target", typeof(object), typeof(ExtendedBinding),
new FrameworkPropertyMetadata()
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
});
public Object Target
{
get { return GetValue(ExtendedBinding.TargetProperty); }
set { SetValue(ExtendedBinding.TargetProperty, value); }
}
#endregion
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property.Name == ExtendedBinding.SourceProperty.Name)
{
//no loop wanted
if (!object.ReferenceEquals(Source, Target))
Target = Source;
}
else if (e.Property.Name == ExtendedBinding.TargetProperty.Name)
{
//no loop wanted
if (!object.ReferenceEquals(Source, Target))
Source = Target;
}
}
}