0
votes

I have an mvvm framework much like Josh Smith's sample. Problem is that I've just discovered that every time I display a viewmodel, for some reason, the associated view constructor is firing TWICE. And this is messing things up elsewhere in the app. Of course, in both case, the call stack is empty, external, so I can't tell who is doing the 'newing'. I know it's not me, I don't 'new' the view anywhere. It's not duplicate datatemplates because it doesn't even allow duplicate templates.

1) How can I figure out who is newing the view?
2) how can I get hooked into the "magic" between newing my viewmodel, and when the behind the scenes of WPF auto figures out what view to use and news the view?

MORE INFORMATION:

Just like Josh Smith example, I have datatemplates that associate a viewmodel to a view. Just like Josh Smith, I have a collection of viewmodels bound to a tab control. When a new viewmodel is created and added to that collection, the magic box uses the datatemplates in the xaml to figure out the view, the magic box news the view, binds the datacontext of the view to my viewmodel and a new tab appears. All this happends behind the scenes within .net. I never new the view. I only new the viewmodel and then add it to a collection.

NARROWED DOWN TO PROBLEM XAML:

If I use the ComboBox, for some reason, that causes a new view to be created from the Items collection which is a list of ViewModels. But if I use the menu, the extra view is not created.

<!--
<ComboBox Name="TabMenus" ItemsSource="{Binding RelativeSource= {RelativeSource FindAncestor,  AncestorType={x:Type lc:MultiStepPanel}},  Path=Items}" Width="15" Height="15" Margin="2" >
    <ComboBox.ItemContainerStyle>
        <Style TargetType="ComboBoxItem" >
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBlock Text="{Binding VisibleDisplayName}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>
-->
<Menu Name="TabMenus" Style="{StaticResource TabMenuDropDownStyle}" >
     <MenuItem Style="{StaticResource TabMenuButtonStyle}"
               ItemsSource="{Binding RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type lc:MultiStepPanel}},  Path=Items}"  
               ItemContainerStyle="{StaticResource TabMenuItem}" />
</Menu>

Both controls have the exact same ItemsSource xaml. Why does the combo trigger a new view?

1
Throw an exception in the constructor. I'll bet it'll load an xaml file when VS snags it.user1228
Where are you initilizing the ViewModel?jcvegan
There is no where near enough information here for anyone to be helpful to you. WPF isn't going to just instantiate a view for you, you must be telling it which view to use (and instantiate) somehow, if you don't know how that is happening and can't explain it to us, there's no way we can help you.CodingGorilla
I updated the question with more info. There is a datatemplate that associates the viewmodel to a viewhappyfirst
Any way we could get you to post some of your code?EtherDragon

1 Answers

0
votes

You so do not have enough information for a real answer, so lets start with a guess. At least I can explain to others how WPF and MVVM usually load a Window.

App.xaml usually has a StartupUri.

<Application x:Uid="Application_1" x:Class="WpfLocalizationExample.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml"
             >
    <Application.Resources>

    </Application.Resources>
</Application>

That does the "new".

If you are using MVVM, the new is usually done in the App.xaml.cs file.

protected override void OnStartup(StartupEventArgs e)
    // Load the Window and View Models
    base.OnStartup(e);
    var viewmodel = new MainWindowViewModel();
    var main = new MainWindow();
    main.DataContext = viewmodel;
    main.Show();
}

My guess is that you are doing both if you are seeing two constructors being fired however, I also would guess you aren't doing the "main.Show()" otherwise you would see two windows.