2016-11-08 1 views
1

J'ai ce bug wierd. Lorsque je construis mon projet, il affiche toujours deux occurrences de ma fenêtre singleton. Here is video de ce qui se passe. Bien que je ne pense pas que ça va aider anyting, voici la plupart des xaml de la fenêtre. Dans le code derrière sont juste des événements pour le mouvement de la souris et un événement de fermeture.Bogue studio visuel lors de la construction

<Window x:Class="Scoreboard.OutputWindow" 
    d:DataContext="{d:DesignInstance viewModel:ControlPanel}" 
    Title="OutputWindow" Height="375" Width="540" 
    Background="{Binding AppData.Settings.Color, Converter={converters:ColorToBrushConverter}}" 
    MouseLeftButtonDown="football_MouseLeftButtonDown" 
    MouseLeftButtonUp="football_MouseLeftButtonUp" 
    MouseMove="football_MouseMove"> 
    <Window.InputBindings> 
     <KeyBinding Modifiers="Control" Key="F" Command="{Binding FullScreenCommand}" /> 
    </Window.InputBindings> 
    <Grid ...> 
    </Grid> 
</Window> 

Cette fenêtre est un singleton dans mon ViewModel. J'y accède juste à partir de là. Cela arrive sur mes deux PC.

EDIT: Lorsque je le supprime du ViewModel, cela ne se produit plus. Mais j'ai un peu besoin de ça là-bas. EDIT2: Here is nouveau projet avec cette fenêtre. Il ne se comporte pas exactement de la même manière, mais lorsque vous faites des changements, il se base sur le débogage, puis sur sturtup il crée une autre OutputWindow qui n'est pas interceptée par le breakpoint dans le constructeur.

+0

Avez-vous défini un point d'arrêt dans le constructeur pour voir d'où provient la seconde instance? – ChrisF

+1

C'est juste de construire, ça ne commence même pas. Les deux instances ne devraient pas être là. – Korhak

+0

Avez-vous des 'Build Events' dans les propriétés du projet? (Surtout les commandes post-construction.) – haindl

Répondre

1

La cause racine de votre problème est la ligne suivante dans votre ViewModel:

public ViewModel() 
{ 
    OutputWindow.IsEnabled = true; 
} 

Cela crée implicitement un new OutputWindow() dans le getter de la propriété:

private OutputWindow _outputWindow; 
public OutputWindow OutputWindow => 
    _outputWindow ?? (_outputWindow = new OutputWindow { DataContext = this }); 

Le constructeur ressemble alors à ce :

public OutputWindow() 
{ 
    InitializeComponent(); 
    Show(); 
} 

Ce ne serait pas si mauvais au moment, mais chaque fois que votre MainWindow est instancié, une nouvelle instance de ViewModel est implicitement créé et à cause de ce code dans le MainWindow:

<Window.DataContext> 
    <local:ViewModel /> 
</Window.DataContext> 

D'accord, ce qui explique pourquoi le OutputWindow est apparaître au démarrage - Mais pourquoi cela se voit-il sur la construction?
(. Ou dans mon cas, même si vous ouvrez le code XAML de MainWindow.xaml dans Visual Studio)

Si trouvé le coupable et il est ce petit bijou ici qui provient de devenv.exe:

TestApplication.exe!TestApplication.OutputWindow.OutputWindow() Line 15 
TestApplication.exe!TestApplication.ViewModel.OutputWindow.get() Line 6 
TestApplication.exe!TestApplication.ViewModel.ViewModel() Line 10 
... 
mscorlib.dll!System.Activator.CreateInstance(System.Type type, bool nonPublic) 
... 
Microsoft.VisualStudio.DesignTools.Platform.dll!Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.ClrObjectInstanceBuilder.Instantiate(Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.IInstanceBuilderContext context, Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.ViewNode viewNode = {Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.ViewNode}) Unknown 
Microsoft.VisualStudio.DesignTools.Platform.dll!Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.ViewNodeManager.CreateInstance(Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.IInstanceBuilder builder, Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.ViewNode viewNode) Unknown 
Microsoft.VisualStudio.DesignTools.Platform.dll!Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.ViewNodeManager.Instantiate(Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.ViewNode viewNode = {Microsoft.VisualStudio.DesignTools.Platform.InstanceBuilders.ViewNode}) Unknown 
... 
XDesProc.exe!Microsoft.VisualStudio.DesignTools.DesignerContract.Isolation.DesignerProcess.RunApplication() 
... 
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() 

Alors, pourquoi ça arrive?
Lors de la construction ou à l'ouverture du concepteur XAML, Visual Studio démarre un thread et demande à XDesProc.exe de créer une nouvelle instance de votre MainWindow.
(XDesProc.exe est le composant qui est responsable du concepteur XAML dans Visual Studio et peut-être le concepteur devrait rafraîchir si vous construisez un projet.)

Et à partir de là, le chemin est comme indiqué ci-dessus:
Une nouvelle ViewModel est créé dans le DataContext implicite du MainWindow qui crée implicitement une nouvelle instance du OutputWindow dans le getter de la propriété qui à son tour appelle Show() sur lui-même. Et voilà, vous avez votre OutputWindow à l'écran!
Dans certains cas, il y a même deux OutputWindows montrant mais c'est seulement parce que le concepteur (ou peut-être un autre composant) est appelé deux fois.

Alors, bottom line - De quoi avez-vous besoin pour corriger votre code?
Il existe plusieurs solutions possibles.
Le plus important, vous devez arrêter la création implicite du OutputWindow dans le ViewModel. Vous pouvez y parvenir en faisant un (ou plusieurs) des éléments suivants:

  • Retirez OutputWindow.IsEnabled = true; dans le constructeur de ViewModel. Ne pas appeler Show(); dans le constructeur de OutputWindow. Ne pas instancier votre ViewModel implicitement en utilisant <Window.DataContext><local:ViewModel />.

Je pense qu'il est juste de dire qu'il est tout simplement faux de montrer implicitement une fenêtre si vous venez de créer une instance d'un simple ViewModel. Donc, si vous rompez cette chaîne malencontreuse d'événements implicites, votre problème disparaîtra pour toujours.

+0

Merci, bonne description détaillée de ce qui se passait. Le 'OutputWindow.IsEnabled = true' était là juste pour que le getter soit appelé. Comme vous l'avez écrit, j'ai supprimé 'Show()' du constructeur et l'ai déplacé après l'initialisation de 'MainWindow' et le problème a été résolu. Bravo pour vous. – Korhak

+0

@Korhak Vous êtes les bienvenus! Content que je puisse t'aider! :-) – haindl