Wpf DependencyObject.AssociatedObject始终为空

Wpf DependencyObject.AssociatedObject始终为空,wpf,Wpf,我正在尝试编写一个客户行为,如果我的“可见性”(在本例中只是一个bool)属性为false,则将一些列宽设置为0。。。我的问题是,当我的on changed事件触发它时,我的AssociatedObject总是空的 这是相关的示例代码,mybe有人可以看到我的错误 public static readonly DependencyProperty VisibilityProperty = DependencyProperty.Register("Visibility", ty

我正在尝试编写一个客户行为,如果我的“可见性”(在本例中只是一个bool)属性为false,则将一些列宽设置为0。。。我的问题是,当我的on changed事件触发它时,我的AssociatedObject总是空的

这是相关的示例代码,mybe有人可以看到我的错误

  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;
    }
}