Ivan
Ivan

Reputation: 81

How to avoid creating instance of View with MVVM (WPF)

I just recognized that, each time when i use MVVM and try to show a ViewModel with its View, a instance of the View will be created, although i just use the same ViewModel.

In my View is a GridView. I wrote this in the code-behind to call the event of ViewModel.

private void gridView_SelectionChanged(object sender, SelectionChangeEventArgs e)
{
    DataContext.CallOnClick((DataContext as IHasSelectedItem<IViewModel>)?.SelectedItem);
}

The problem with that is, if i defined some events in code-behind of the View, i will get the events more than once, because instances of the View are always be created and each instance sends the ViewModel the event.

Is there somebody, who has this problem, too. Or somebody knows the solution? Thanks a lot!

-------------------------------------------------------------

Add: I have changed my code-behind like that. It works, i got the event only once. But i am not sure, whether the other views have been disposed.

public TestView()
{
   InitializeComponent();
   IsVisibleChanged += TestView_IsVisibleChanged;
}

private void TestView_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
{
   if (e.NewValue.Equals(false))
   {
       MyGridView.SelectionChanged -= gridView_SelectionChanged;                
   }
   else
   {
       MyGridView.SelectionChanged += gridView_SelectionChanged;
   }
}

private void gridView_SelectionChanged(object sender, SelectionChangeEventArgs e)
{
   DataContext.CallOnClick((DataContext as IHasSelectedItem<IViewModel>)?.SelectedItem);
}

Upvotes: 0

Views: 718

Answers (1)

Sheridan
Sheridan

Reputation: 69959

The MVVM solution to your problem is to not use the IsVisibleChanged event at all. Instead of that, we simply create a bool property in the view model:

private bool isVisible = false;

public bool IsVisible
{
    get { return isVisible; }
    set { isVisible = value; NotifyPropertyChanged("IsVisible"); }
}

Now you can data bind this property to the Visibility property of the relevant control using a BooleanToVisibilityConverter:

Visibility="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"

Now whenever the Visibility property changes, the IsVisible setter will get called, so you can handle it there:

public bool IsVisible
{
    get { return isVisible; }
    set 
    {
        isVisible = value; 
        NotifyPropertyChanged("IsVisible");
        // Handle the change of visibility here... maybe call a method from here?
    }
}

Upvotes: 2

Related Questions