Wpf DependencyObject.AssociatedObject始终为空
我正在尝试编写一个客户行为,如果我的“可见性”(在本例中只是一个bool)属性为false,则将一些列宽设置为0。。。我的问题是,当我的on changed事件触发它时,我的AssociatedObject总是空的 这是相关的示例代码,mybe有人可以看到我的错误Wpf DependencyObject.AssociatedObject始终为空,wpf,Wpf,我正在尝试编写一个客户行为,如果我的“可见性”(在本例中只是一个bool)属性为false,则将一些列宽设置为0。。。我的问题是,当我的on changed事件触发它时,我的AssociatedObject总是空的 这是相关的示例代码,mybe有人可以看到我的错误 public static readonly DependencyProperty VisibilityProperty = DependencyProperty.Register("Visibility", ty
public static readonly DependencyProperty VisibilityProperty =
DependencyProperty.Register("Visibility", typeof(bool), typeof(HideRadGridViewColumnBehavior),
new PropertyMetadata(OnVisibilityPropertyChanged));
private static void OnVisibilityPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
if (((HideRadGridViewColumnBehavior)target).AssociatedObject == null)
MessageBox.Show("AssociatedObject is null");
}
谢谢你的帮助 你是如何看待这种行为的?你们能展示一些行为准则吗
AssociatedObject可以在调用之后设置,也可以通过在
中列出行为来设置。感谢Markus Hütter的想法。这就是我在PasswordBox行为中的实现方式(请参见下面代码中的注释):
行为:
public class PasswordBehavior : Behavior<PasswordBox>
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(string), typeof(PasswordBehavior), new PropertyMetadata(default(string)));
private object _value;
private bool _skipUpdate;
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
protected override void OnAttached()
{
// in my case on OnAttached() called after OnPropertyChanged
base.OnAttached();
AssociatedObject.PasswordChanged += PasswordBox_PasswordChanged;
// using _value saved before in OnPropertyChanged
if (_value != null)
{
AssociatedObject.Password = _value as string;
}
}
protected override void OnDetaching()
{
AssociatedObject.PasswordChanged -= PasswordBox_PasswordChanged;
base.OnDetaching();
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
// in my case this called before OnAttached(), so that's why AssociatedObject is null on first call
base.OnPropertyChanged(e);
if (AssociatedObject == null)
{
// so, let'save the value and then reuse it when OnAttached() called
_value = e.NewValue as string;
return;
}
if (e.Property == PasswordProperty)
{
if (!_skipUpdate)
{
_skipUpdate = true;
AssociatedObject.Password = e.NewValue as string;
_skipUpdate = false;
}
}
}
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
_skipUpdate = true;
Password = AssociatedObject.Password;
_skipUpdate = false;
}
}
公共类密码行为:行为
{
公共静态只读从属属性PasswordProperty=
Register(“Password”、typeof(string)、typeof(PasswordBehavior)、newpropertyMetadata(default(string));
私有对象_值;
私人布卢斯基普日期;
公共字符串密码
{
获取{return(string)GetValue(PasswordProperty);}
set{SetValue(PasswordProperty,value);}
}
受保护的覆盖无效附加()
{
//在我的例子中,OnAttached()在OnPropertyChanged之后调用
base.onatached();
AssociatedObject.PasswordChanged+=PasswordBox\u PasswordChanged;
//在OnPropertyChanged中使用之前保存的_值
如果(_值!=null)
{
AssociatedObject.Password=\作为字符串的值;
}
}
附加时受保护的覆盖无效()
{
AssociatedObject.PasswordChanged-=PasswordBox\u PasswordChanged;
base.OnDetaching();
}
受保护的重写无效OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
//在我的例子中,这是在OnAttached()之前调用的,所以这就是AssociatedObject在第一次调用时为null的原因
根据改变的财产(e);
if(AssociatedObject==null)
{
//因此,让我们保存该值,然后在调用OnAttached()时重用它
_value=e.NewValue作为字符串;
返回;
}
if(e.Property==PasswordProperty)
{
如果(!\u日期)
{
_skipUpdate=true;
AssociatedObject.Password=e.NewValue作为字符串;
_skipUpdate=false;
}
}
}
私有无效密码箱\u密码已更改(对象发送方,RoutedEventArgs e)
{
_skipUpdate=true;
Password=AssociatedObject.Password;
_skipUpdate=false;
}
}
转到AssociatedObject属性,右键单击->查找用法。你会发现属性被设置为null或根本没有设置。对-但这是从XAML中设置的,在你编译应用程序之前,XAML不会实际生成代码。。。我的意思是,我可能说得不对,但你明白了,关键是我在代码中看不到任何指向它被设置位置的引用。之后,你可以在这个属性的setter中设置断点。xaml代码似乎没有设置此属性的值。这就是行为的设置方式…`1Oh-该行为还没有任何代码,导致仅发生在我的OnVisibilityPropertyChanged中,但如果我没有访问关联对象的权限,我将无法执行任何操作:(@Kenn,好的,那么很可能绑定发生在附加之前。无论您在changedhandler中拥有什么,都将其放在一个单独的方法中,您可以从changedhandler调用该方法。然后在您的行为中重写onatached()
,并从那里调用该方法,那么一切都应该很好
public class PasswordBehavior : Behavior<PasswordBox>
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(string), typeof(PasswordBehavior), new PropertyMetadata(default(string)));
private object _value;
private bool _skipUpdate;
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
protected override void OnAttached()
{
// in my case on OnAttached() called after OnPropertyChanged
base.OnAttached();
AssociatedObject.PasswordChanged += PasswordBox_PasswordChanged;
// using _value saved before in OnPropertyChanged
if (_value != null)
{
AssociatedObject.Password = _value as string;
}
}
protected override void OnDetaching()
{
AssociatedObject.PasswordChanged -= PasswordBox_PasswordChanged;
base.OnDetaching();
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
// in my case this called before OnAttached(), so that's why AssociatedObject is null on first call
base.OnPropertyChanged(e);
if (AssociatedObject == null)
{
// so, let'save the value and then reuse it when OnAttached() called
_value = e.NewValue as string;
return;
}
if (e.Property == PasswordProperty)
{
if (!_skipUpdate)
{
_skipUpdate = true;
AssociatedObject.Password = e.NewValue as string;
_skipUpdate = false;
}
}
}
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
_skipUpdate = true;
Password = AssociatedObject.Password;
_skipUpdate = false;
}
}