2009-11-18 24 views
3

J'ai actuellement un projet WPF qui a une fenêtre principale, et de nombreux UserControls qui sont des enfants de cette fenêtre. Beaucoup d'enfants de cette fenêtre sont des onglets. J'ai réussi à remplacer ma fenêtre principale par un contrôle utilisateur qui implémente presque exactement la même fonctionnalité que la fenêtre principale. Le remplacement de la fenêtre par un UserControl a introduit un problème - actuellement, notre application détermine quel onglet de programmation afficher en fonction de la fenêtre parente en utilisant la méthode Window.FindName montrée ci-dessous. Par conséquent, j'ai besoin de remplacer le Application.Current.MainWindow avec une description appropriée de mon contrôle utilisateur principal. Voir la méthode C# d'erreur ci-dessous et l'instanciation wpf des onglets pour plus de clarté.Comment trouver les enfants d'un UserControl au lieu d'une fenêtre - en remplaçant Window.FindName

Remarque En ce qui concerne la méthode Window.FindName() - la raison pour laquelle il ne fonctionne pas après je l'ai remplacé par un UserControl est parce que la méthode recherche findname vers le haut dans l'arborescence visuelle, as described here.

Est-ce que quelqu'un sait comment trouver un contrôle utilisateur basé sur le x: Name, similaire à Application.Current.MainWindow? En outre, existe-t-il une meilleure façon de trouver UserControl que de rechercher la chaîne x: Name au cas où il serait renommé?

Comment nous trouvons actuellement MainWindow - nécessité de trouver maintenant MainUserControl:

(C#) 
private static void SetCurrentProgram(int num) 
    { 
     Window window = Application.Current.MainWindow; 
     ProgrammingTab programmingTab1 = window.FindName("ProgrammingTab1") as ProgrammingTab; 
     ProgrammingTab programmingTab2 = window.FindName("ProgrammingTab2") as ProgrammingTab; 

     programmingTab1.Visibility = num == 1 ? Visibility.Visible : Visibility.Collapsed; 
     programmingTab2.Visibility = num == 2 ? Visibility.Visible : Visibility.Collapsed; 

    } 

instanciation des onglets de programmation.

(xaml) 
<Grid> 
<ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab1" Program="1" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" /> 
<ProgrammingControl:ProgrammingTab x:Name="ProgrammingTab2" Program="2" IsVisibleChanged="ProgrammingTab_IsVisibleChanged" /> 
</Grid> 

Répondre

0

J'ai trouvé une solution de contournement à ce problème: J'ai créé un nouvel algorithme basé sur un autre algorithme d'utilisateur StackOverflow qui a trouvé récursivement les enfants d'un DependencyObject. Trouver my solution here. Si vous déclarez la méthode FindChild() dans mon autre poste au sein de public static class UIHelper {} vous pouvez résoudre le problème en faisant ceci:

ProgrammingTab programmingTab1 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab1"); 
    ProgrammingTab programmingTab2 = UIHelper.FindChild<ProgrammingTab>(Application.Current.MainWindow, "ProgrammingTab2"); 

Il utilise encore le code de procédure au lieu de XAML déclarative pour les fixations comme suggéré Rayburns. Si cela fonctionne, sa solution sera beaucoup plus efficace car elle ne traversera pas tout un arbre mais changera simplement la visibilité des onglets basés sur un convertisseur. Je vais tester cette solution maintenant et voir comment ça se passe.

La raison pour laquelle FindName() ne fonctionne pas correctement est décrite dans post here.

2

Il semble que votre application soit développée dans un style très proche de WinForms. Pour coller avec ce style et simplement répondre à votre question, vous pouvez FindName() pour trouver le UserControl et encore pour trouver le ProgrammingTab, comme ceci:

var userControl = (MyUserControl)Application.Current.MainWindow.FindName("userControlName"); 
var programmingTab1 = (ProgrammingTab)userControl.FindName("ProgrammingTab1"); 
var programmingTab2 = (ProgrammingTab)userControl.FindName("ProgrammingTab2"); 
... 

Cependant, je vous recommande de regarder en utilisant des fonctionnalités avancées de WPF telles que liaison de données. Vous pouvez avoir un DependencyProperty "CurrentProgram" sur un objet singleton référencé par une propriété statique, et simplement lui assigner une Visiblité en utilisant un convertisseur.

<ProgrammingTab Visibilty="{Binding CurrentProgram, 
    Source={x:Static MyState.Instance}, 
    Converter={x:Static VisibleIfEqualConverter}, 
    ConverterParameter=1}" ...> 
    ... 

Avec ce changement, votre SetCurrentProgram devient simplement:

public void SetCurrentProgram(int num) 
{ 
    MyState.Instance.CurrentProgram = num; 
} 

La beauté de cette technique est que tout ProgrammingTab partout dans votre application apparaîtra automatiquement ou disparaître vaulue de chaque fois que MyState.Instance.CurrentProgram change , sans avoir besoin de les trouver avec FindName() ou autrement.

+0

Je vous remercie tous de votre perspicacité - Je vais vérifier votre suggestion WPF. Cependant, j'ai trouvé que la ligne * var userControl = (MyUserControl) Application.Current.MainWindow.FindName ("userControlName"); * finit par retourner null. J'ai confirmé le x: Le nom était correct. J'ai créé une nouvelle fenêtre principale et instancié le contrôle de l'utilisateur dans la grille de la fenêtre. Aucune suggestion? Je peux fournir plus d'informations si nécessaire. – CrimsonX

+0

En regardant plus loin - je crois que le problème a à voir avec l'une des deux choses: 1) Le * (MyUserControl) Application.Current.MainWindow.FindName ("userControlName"); * en quelque sorte être dans le mauvais NameScope (voir http : //msdn.microsoft.com/en-us/library/ms746659.aspx pour plus d'informations) OU 2) Je vais dans le mauvais chemin et je devrais utiliser le VisualTreeHelper: http: // stackoverflow. com/questions/636383/wpf-ways-to-find-controls – CrimsonX

+0

Vous dites que vous avez "instancié le contrôle utilisateur dans la grille de la fenêtre". Avez-vous fait cela dans le code? Si oui, vous souvenez-vous d'appeler RegisterName()? Ce n'est pas fait pour toi. Si vous l'avez fait en XAML, y a-t-il des objets qui ont leur propre NameScope? –