6
votes

I have wizard project that works with ContentControl which contains user controls. I do the instantiation through the XAML file at my main window:

    <DataTemplate DataType="{x:Type ViewModel:OpeningViewModel}">
        <view:OpeningView/>
   </DataTemplate>

    <DataTemplate DataType="{x:Type ViewModel:SecondUCViewModel}">
        <view:SecondUCView/>
    </DataTemplate>

But when I navigate between the UC's it seems that the UC's aren't works like "keep alive", Every UC switching creates new instance. How can I avoid it? I want create for every UC just one instance and navigate between those instances only without creating new instances.

I know how write singleton but my project based on MVVM and I'm quite new at WPF so I'm not sure what is the best way to do this.

Thanks

Update:

Here the code of the viewModel:

In the viewModel I have :

private ObservableCollection _pages = null; private NavigationBaseViewModel _currentPage;

    #endregion

    #region Properties

    public int CurrentPageIndex
    {
        get
        {
            if (this.CurrentPage == null)
            {
                return 0;
            }
            return _pages.IndexOf(this.CurrentPage);
        }
    }

    public NavigationBaseViewModel CurrentPage
    {
        get { return _currentPage; }

        private set
        {
            if (value == _currentPage)
                return;

            _currentPage = value;
            OnPropertyChanged("CurrentPage");
        }
    }

private ICommand _NavigateNextCommand; public ICommand NavigateNextCommand { get { if (_NavigateNextCommand == null) { _NavigateNextCommand = new RelayCommand(param => this.MoveToNextPage(), param => CanMoveToNextPage); } return _NavigateNextCommand; } }

    private ICommand _NavigateBackCommand;
    public ICommand NavigateBackCommand
    {
        get
        {
            if (_NavigateBackCommand == null)
            {
                _NavigateBackCommand = new RelayCommand(param => this.MoveToPreviousPage(), param => CanMoveToPreviousPage);
            }
            return _NavigateBackCommand;
        }
    }



   private bool CanMoveToNextPage
    {
        get
        {
            return this.CurrentPage != null && this.CurrentPage.CanMoveNext;
        }
    }

    bool CanMoveToPreviousPage
    {
        get { return 0 < this.CurrentPageIndex && CurrentPage.CanMoveBack; }
    }

    private void MoveToNextPage()
    {
        if (this.CanMoveToNextPage)
        {
            if (CurrentPageIndex >= _pages.Count - 1)
                Cancel();
            if (this.CurrentPageIndex < _pages.Count - 1)
            {
                this.CurrentPage = _pages[this.CurrentPageIndex + 1];
            }
        }
    }

    void MoveToPreviousPage()
    {
        if (this.CanMoveToPreviousPage)
        {
            this.CurrentPage = _pages[this.CurrentPageIndex - 1];
        }
    }

And the ContentControl which contains the UC`s binded to CurrentPage

2
How do you navigate between those two UCs? Could you post the code?Florian Gl
See my main topic, I added the code there.Ofir

2 Answers

1
votes

You can do that by hardcoding the UserControls in XAML, instead of using DataTemplates. DataTemplates will create new Controls every time they are instantiated. However, since you use MVVM, you could also move all data you want persisted between the changes to the ViewModels, and make sure that the ViewModel objects are always the same. Then, the DataTemplates would still create new controls, but they would contain the same information as before.

0
votes

I have recently come up against the same issue with my views in MVVM. Basically, I wanted to cache views that took a while to render. If you are familiar with the ViewModelLocator, this approach should be straight forward.

In the client (e.g. WPF) project I created a ViewLocator class that looked like this:

public class ViewLocator : ObservableObject
{
    #region Properties

    private View _myView;
    public View MyView
    {
        get { return _myView; }
        set { Set(() => MyView, ref _myView, value); }
    }

    #endregion Properties

    #region Constructors

    public ViewLocator()
    {
        RegisterViews();
    }

    #endregion Constructors

    #region Private Methods

    private void RegisterViews()
    {
        MyView = new View();
    }

    #endregion Private Methods
}

And to use this in a data template I specified the ViewLocator as an static application resource so only one instance is ever instantiated - in my case I put it in in App.xaml. To use the ViewLocator and it's "View" properties, I did the following:

<vl:ViewLocator x:Key="ViewLocator" />
<DataTemplate DataType="{x:Type vm:ViewModel}">
    <ContentControl Content="{Binding Source={StaticResource ViewLocator}, Path=MyView}" />
</DataTemplate>

By doing it this way, each view is only instantiated once and can be reused.