这里我有一个简单的混合行为。它有一个DependencyProperty
我希望在OnAttached
初始化期间执行某些操作。但我不能,因为行为似乎在它被初始化之前就被附加了!
用法:
<Button>
<e:Interaction.Behaviors>
<local:TestBehavior Test1="{Binding ValueOnViewModel}"/>
</e:Interaction.Behaviors>
<Button>
定义:
class TestBehavior : Behavior<FrameworkObject>
{
public static readonly DependencyProperty Test1Property
= DependencyProperty.Register("Test1", typeof(int), typeof(TestBehavior),
new PropertyMetadata(OnTest1Property_Changed));
private static void OnTest1Property_Changed(DependencyObject sender,
DependencyPropertyChangedEventArgs args)
{
// This gets called _after_ OnAttached!
}
public int Test1
{
get { return (int)GetValue(Test1Property); }
set { SetValue(Test1Property, value); }
}
protected override void OnAttached()
{
base.OnAttached();
// No matter what Test1Property is bound to in XAML 'a' will be default
// value because as this point the Behavior is attached, but not
// initialized!
int a = Test1;
}
}
这让我觉得很奇怪。在这个简单的例子中,我可以通过在OnTest1Property_Changed中而不是在OnAttached中执行初始化来解决问题(尽管在静态上下文而不是实例上下文中有轻微的不便)。
然而,如果我有一个相当不那么琐碎的行为有多个属性怎么办?在行为的一些用法中,可以明确地设置所有DP,而在其他情况下,在使用未明确设置的DP的默认值时,可以仅设置一些DP。我可以处理行为定义的所有DP的更改事件,但是我无法知道客户端在XAML中明确设置了哪个DP,所以我无法知道在初始化完成之前必须发生更改通知
那么,在这个非平凡的情况下,我怎么可能知道行为的初始化何时完成?这似乎是一个明显的弱点,我只能假设我错过了一些明显的东西。
[更新]
使用Sorskoot的建议我敲了这个简单的基类,我可以用它作为我的行为的基础。
public class BehaviorBase<T> : Behavior<T> where T : FrameworkElement
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += AssociatedObject_Loaded;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= AssociatedObject_Loaded;
}
protected virtual void OnLoaded()
{
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
OnLoaded();
}
}
答案 0 :(得分:2)
我建议在Loaded
方法期间附加OnAttached
事件并在那里进行初始化。
protected override void OnAttached()
{
base.OnAttached();
base.AssociatedObject.Loaded += onloaded;
}
private void onloaded(object sender, RoutedEventArgs e)
{
int a = Test1;
// Test1 should contain a value here.
}