C# 如何在Silverlight中订阅自定义控件中附加属性的事件?

C# 如何在Silverlight中订阅自定义控件中附加属性的事件?,c#,silverlight,xaml,mvvm,C#,Silverlight,Xaml,Mvvm,我正在开发自定义控件,可以在我的应用程序UI中用于交互。因此,我的想法是控件将绑定到包含其事件的IInteractionsProvider。然后,我将调用此提供程序上的方法,该方法将向我的控件引发事件,以执行它需要执行的操作 问题是,我不知道如何在自定义控件中正确订阅eventInteractionRequired 基本上,我不知道如何正确地钩住和解开事件,以及在什么时候进行内部控制 public interface IInteractionsProvider { eve

我正在开发自定义控件,可以在我的应用程序UI中用于交互。因此,我的想法是控件将绑定到包含其事件的
IInteractionsProvider
。然后,我将调用此提供程序上的方法,该方法将向我的控件引发事件,以执行它需要执行的操作

问题是,我不知道如何在自定义控件中正确订阅event
InteractionRequired

基本上,我不知道如何正确地钩住和解开事件,以及在什么时候进行内部控制

public interface IInteractionsProvider
    {
        event EventHandler InteractionRequested;

        void RequestInteraction(Action<object> callback);
    } 



public class MyInteractions : Control
    {
        public static readonly DependencyProperty ContainerProperty =
            DependencyProperty.Register("Container", typeof(Grid), typeof(IdattInteractions), new PropertyMetadata(null));

        public static readonly DependencyProperty InteractionsProviderProperty =
            DependencyProperty.Register("InteractionsProvider", typeof(IInteractionsProvider), typeof(IdattInteractions), new PropertyMetadata(null));

        public IdattInteractions()
        {
            DefaultStyleKey = typeof(MyInteractions);
        }

        public Grid Container
        {
            get { return GetValue(ContainerProperty) as Grid; }
            set { this.SetValue(ContainerProperty, value); }
        }

        public IInteractionsProvider InteractionsProvider
        {
            get { return (IInteractionsProvider)GetValue(InteractionsProviderProperty); }
            set { this.SetValue(InteractionsProviderProperty, value); }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (System.ComponentModel.DesignerProperties.IsInDesignTool) return;

            if (this.InteractionsProvider == null)
            {
                throw new NotSupportedException("InteractionsProvider wasn't specified. If you don't need interactions on this view - please remove MyInteractions from XAML");
            }

            if (this.Container != null)
            {
                if (this.Container.GetType() != typeof(Grid))
                {
                    throw new NotSupportedException("Specified container must be of Grid type");
                }
            }
            else
            {
                this.Container = TreeHelper.FindParentGridByName(this, "LayoutRoot") ?? TreeHelper.FindParent<Grid>(this);

                if (this.Container == null)
                {
                    throw new NotSupportedException("Container wasn't specified and parent Grid wasn't found");
                }
            }
        }
    }
公共接口IInteractionsProvider
{
请求的事件处理程序交互;
void-RequestInteraction(动作回调);
} 
公共类:控件
{
公共静态只读从属属性ContainerProperty=
Register(“容器”、typeof(网格)、typeof(IdattInteractions)、newpropertyMetadata(null));
公共静态只读从属属性InteractionProviderProperty=
DependencyProperty.Register(“InteractionProvider”、typeof(IIinteractionsProvider)、typeof(IdattInteractions)、new PropertyMetadata(null));
公共IDataInteractions()
{
DefaultStyleKey=typeof(MyInteractions);
}
公共网格容器
{
获取{返回GetValue(ContainerProperty)作为网格;}
set{this.SetValue(ContainerProperty,value);}
}
公共交互提供程序交互提供程序
{
获取{return(IInteractionsProvider)GetValue(InteractionsProviderProperty);}
set{this.SetValue(InteractionProviderProperty,value);}
}
应用程序模板()上的公共重写无效
{
base.OnApplyTemplate();
if(System.ComponentModel.DesignerProperties.IsInDesignTool)返回;
if(this.InteractionsProvider==null)
{
抛出新的NotSupportedException(“未指定InteractionsProvider。如果在此视图上不需要交互-请从XAML中删除MyInteractions”);
}
if(this.Container!=null)
{
if(this.Container.GetType()!=typeof(Grid))
{
抛出新的NotSupportedException(“指定的容器必须是网格类型”);
}
}
其他的
{
this.Container=TreeHelper.FindParentGridByName(this,“LayoutRoot”)??TreeHelper.FindParent(this);
if(this.Container==null)
{
抛出新的NotSupportedException(“未指定容器,未找到父网格”);
}
}
}
}

这就是你要找的吗

public IInteractionsProvider InteractionsProvider 
{ 
    get { return (IInteractionsProvider)GetValue(InteractionsProviderProperty); } 
    set {
        var oldValue = this.InteractionsProvider;
        if (oldValue != null)
            oldValue.InteractionRequested -= this.HandleInteractionRequested;
        if (value != null)
            value.InteractionRequested += this.HandleInteractionRequested;
        this.SetValue(InteractionsProviderProperty, value);
    } 
} 

private void HandleInteractionRequested(object sender, EventArgs e)
{
    //...
}

要附加到依赖项属性上的事件(或在分配依赖项属性时对其执行任何操作),可以使用
PropertyMetadata
上的回调委托

    public static readonly DependencyProperty InteractionsProviderProperty = 
        DependencyProperty.Register("InteractionsProvider", typeof(IInteractionsProvider), typeof(IdattInteractions), new PropertyMetadata(null, OnInteractionsProviderPropertyChanged)); 

    private static void OnInteractionsProviderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

         var source = d As MyInteractions;
         if (source ! = null)
         {
             var oldValue = (IInteractionsProvider)e.OldValue;
             var newValue = (IInteractionsProvider)e.NewValue;
             source.OnInteractionsProviderPropertyChanged(oldValue, newValue);
         }
    }
    private void OnInteractionsProviderPropertyChanged(IInteractionsProvider oldValue, IInteractionsProvider newValue)
    {
         if (oldValue != null)
              oldValue -= InteractionsProvider_InteractionRequested;

         if (newValue != null)
              newValue += InteractionsProvider_InteractionRequested;
    }
    private void InteractionsProvider_InteractionRequested(object sender, EventArgs e)
    {
        // Do Stuff
    }

使用依赖项属性时,始终使用属性更改回调。分配属性时,并不总是调用标准的.NET属性设置器方法。例如,如果使用绑定将其赋值,Silverlight将直接调用
SetValue
,它将不会调用您在答案中包含的setter代码。顺便说一句,newValue从何而来?^^^他说的。XAML解析器完全绕过属性get/set定义。它只是为了方便程序员,仅此而已。除了对GetValue或SetValue的调用之外,您不应该在其中放入任何代码,因为绑定系统会绕过这些代码。@AnthonyWJones谢谢您的提示
newValue
应该是
value
;我纠正了。那phoog建议的方法呢?我更喜欢这种方法,不确定是否有任何顾虑?@katit:请看我对答案的评论谢谢!我想他的新价值应该是价值。我猜在您的示例中的依赖项属性声明中,它应该是OnInteractionsProviderPropertyChanged而不是OnInteractionsProviderProperty,对吗?@katit:nope在这种情况下newValue是newValue。回拨代理分配不正确,应该是
OnInteractionsProviderPropertyChanged
,我已更正。@katit在我的回答中,是的,newValue应该是value。我改正了。