2013-03-08 5 views
5

J'ai UserControlViewModel qui déclenche un événement:Où accéder DataContext dans WinRT XAML UserControl

public event EventHandler<EventArgs> StuffDone; 

Un objet de UserControlViewModel est créé et mis en service à l'intérieur MainPageViewModel:

this.userControlViewModel = new UserControlViewModel(); 

MainPageViewModel est la vue -Modèle pour MainPage.

En MainPage.xaml, j'ai le code suivant pour placer UserControlViewUserControl dans MainPage et son DataContext initialisez:

<views:UserControlView DataContext="{Binding userControlViewModel, Mode=OneWay}" IsHitTestVisible="False"></views:UserControlView> 

Jusqu'à présent, tout fonctionne très bien.

Maintenant, je souhaite m'abonner à l'événement StuffDone à l'intérieur de UserControlView. La première chose qui m'est venue est de le faire à l'intérieur Loaded gestionnaire d'événements de UserControlView; cependant, le DataContext est toujours null. L'analyse du reste des événements UserControl ne m'a donné aucune idée du tout. Où est le bon endroit pour obtenir le DataContext et vous abonner à ses événements?

Merci d'avance.

+2

Douloureux. Il n'y a aucun événement et aucune métadonnée de substitution sur la propriété de dépendance DataContext. Rentrez chez vous, Microsoft, vous êtes saoul. Ce gars a une solution ici: http://dotneteers.net/blogs/vbandi/archive/2013/01/23/datacontextchanged-event-for-winrt.aspx Hacky. – Will

+0

Je l'ai fait avant et ça marche bien pour moi. Mais j'ai utilisé "Mode = TwoWay". Dans l'événement Loaded de UserControl, je peux accéder à ViewModel (bien sûr, vous devez convertir DataCotext à votre ViewModel pour y accéder) – SachiraChin

+0

@Sach, fait quoi exactement? que [Will] (http://stackoverflow.com/users/1228/will) suggéré? Si c'est autre chose, pouvez-vous donner un exemple de ce que vous avez fait? – TheBlueSky

Répondre

1

MISE À JOUR: L'événement DataContextChanged est pris en charge dans WinRT pour Windows 8.1. Utilisez ce qui suit uniquement si vous codez sur WinRT pour Windows 8 ou sur une autre plate-forme qui ne prend pas en charge DataContextChanged.

On dirait qu'il n'y a pas de moyen simple de le faire et la solution de contournement suggérée par Will sur son commentaire est la manière la plus simple d'y aller.

Voici ma version de la solution de contournement qui fonctionne pour moi:

En IDataContextChangedHandler.Generic.cs:

using Windows.UI.Xaml; 

namespace SomeNamespace 
{ 
    public interface IDataContextChangedHandler<in T> where T : FrameworkElement 
    { 
     void DataContextChanged(T sender, DependencyPropertyChangedEventArgs e); 
    } 
} 

En DataContextChangedHelper.Generic.cs:

using Windows.UI.Xaml; 
using Windows.UI.Xaml.Data; 

namespace SomeNamespace 
{ 
    public sealed class DataContextChangedHandler<T> where T : FrameworkElement, IDataContextChangedHandler<T> 
    { 
     private readonly DependencyProperty internalDataContextProperty = 
      DependencyProperty.Register(
       "InternalDataContext", 
       typeof(object), 
       typeof(T), 
       new PropertyMetadata(null, DataContextChanged)); 

     private static void DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) 
     { 
      var control = sender as T; 

      if (control == null) { return; } 

      control.DataContextChanged(control, e); 
     } 

     public void Bind(T control) 
     { 
      control.SetBinding(this.internalDataContextProperty, new Binding()); 
     } 
    } 
} 

Dans UserControlView.xaml.cs:

using Windows.UI.Xaml; 

namespace SomeNamespace 
{ 
    public sealed partial class UserControlView : IDataContextChangedHandler<UserControlView> 
    { 
     private readonly DataContextChangedHandler<UserControlView> handler = new DataContextChangedHandler<UserControlView>(); 

     public UserControlView() 
     { 
      this.InitializeComponent(); 

      this.handler.Bind(this); 
     } 

     public void DataContextChanged(UserControlView sender, DependencyPropertyChangedEventArgs e) 
     { 
      var viewModel = e.NewValue as UserControlViewModel; 

      if (viewModel == null) { return; } 

      viewModel.SomeEventRaised += (o, args) => VisualStateManager.GoToState(this, "TheOtherState", false); 
     } 
    } 
} 

Espérons que cela aide.

+0

Je préfère cette approche: http://amrreda.wordpress.com/2013/01/24/winrt-datacontext-changed-event-and-trigger/ – HappyNomad