2011-11-11 11 views
2

私は、自分のアプリのUI内でインタラクションに使用できるカスタムコントロールに取り組んでいます。ですから、私の考えは、コントロールがイベントを持つIInteractionsProviderにバインドされるということです。そして、私はこのプロバイダーのメソッドを呼び出すことになります。このメソッドは、必要な処理を行うためにコントロールをイベントに発生させます。Silverlightでカスタムコントロール内の添付プロパティのイベントを購読するには?

問題は、カスタムコントロール内のイベント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"); 
       } 
      } 
     } 
    } 

答えて

1

依存関係プロパティのイベントにアタッチする(またはその割り当てられたとき、依存関係プロパティで何かをする)あなたは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 
    } 
+0

phoogの提案はどうですか?私はそのアプローチが気に入っているのではないかと思います。 – katit

+0

@katit:その答えに私のコメントを参照してください – AnthonyWJones

+0

ありがとう!彼のnewValueは価値があるはずです。そして、あなたの例の依存関係プロパティの宣言では、OnInteractionsProviderPropertyChangedではなくOnInteractionsProviderPropertyでなければならないと思いますか? – katit

0

これはあなたが探しているものですか?

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) 
{ 
    //... 
} 
+0

依存関係プロパティを使用する場合は、常にプロパティ変更コールバックを使用してください。プロパティが割り当てられている場合、標準.NETプロパティ設定メソッドが常に呼び出されるわけではありません。たとえば、バインディングを使用してSilverlightに「SetValue」を直接呼び出すと、回答に含まれているセッターコードは呼び出されません。ところで、newValueはどこから来たのですか? – AnthonyWJones

+0

^^^彼は言った。 XAMLパーサーは、プロパティのget/set定義を完全にバイパスします。プログラマの利便性のためにそこにあります。バインドシステムがそのコードをバイパスするため、そこにGetValueまたはSetValueの呼び出し以外のコードを置くべきではありません。 –

+0

@AnthonyWJonesのチップに感謝します。 'newValue'は' value'です。私はそれを修正した。 – phoog

関連する問題