0

I have three tabs in my tab control that I can click through freely and everything works as planned. However, the second I interact with the current tab, the next couple tab changes locks up the tab control to the point where I cannot change a tab and forced to reopen the program. I have tried using custom tab controls, using a content presenter, and data templates but this tab control still locks.

Here is what it looks like normally:

enter image description here

Here is what it looks like when frozen:

enter image description here


This is my tab control in the view:

<controls:ViewModelToViewConverter x:Key="ViewViewModelConverter"/>
...

<TabControl SelectedIndex="{Binding SelectTabIndex, Mode=TwoWay}" >
  <TabItem x:Name="ApInvoicesTab" Header="AP Invoices" > 
     <ContentControl Content="{Binding CurrentViewModel, Converter={StaticResource ViewViewModelConverter}}"/>
   </TabItem>
   <TabItem x:Name="ArInvoicesTab" Header="AR Invoices" >
     <ContentControl Content="{Binding CurrentViewModel, Converter={StaticResource ViewViewModelConverter}}"/>
   </TabItem>
   <TabItem x:Name="HistoryTab" Header="History"> 
     <ContentControl Content="{Binding CurrentViewModel, Converter={StaticResource ViewViewModelConverter}}"/>
   </TabItem>
 </TabControl>

The converter:

public class ViewModelToViewConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null) return null;

        //use naming convention or custom settings here to get view type
        var viewModelType = value.GetType();
        var viewType = Type.GetType(value.ToString().Replace("Model", ""));

        var view = (FrameworkElement)Activator.CreateInstance(viewType);
        view.DataContext = value;
        return view;
    }
}

Main View Model (which is the datacontext for the main view with the tabs):

    //private properties
    private int _selectTabIndex;
    private ViewModelBase _currentViewModel;
    private List<ViewModelBase> _viewModels;


    //Constructor
    public MainViewModel()
    {
        try
        {
            _viewModels = new List<ViewModelBase>
            {
                new ApInvoiceViewModel(),
                new ArInvoiceViewModel(),
                new InvoiceHistoryViewModel()
            };

            PropertyChanged += MainViewModel_PropertyChanged;

            CurrentViewModel = _viewModels[0];
                ((IRefreshable)CurrentViewModel).RefreshData();
        }
        catch (Exception e)
        {

        }
    }

    //Command that displays correct viewmodel
    public RelayCommand<object> SetCurrentViewModelCommand
    {
        get
        {
            return _setCurrentViewModelCommand ?? (_setCurrentViewModelCommand = new RelayCommand<object>(
                      (getType) =>
                      {
                          try
                          {
                              if (getType != null)
                              {
                                  _messageService.ShowWorkingMessage();

                                  CurrentViewModel = _viewModels[(int)getType];

                                  if (CurrentViewModel is IRefreshable)
                                      ((IRefreshable)CurrentViewModel).RefreshData();

                                  _messageService.HideWorkingMessage();
                              }
                              IsLoading = false;
                          }
                          catch (Exception e)
                          {
                              IntegratorJobDAL.SetIntegratorJobError(0, e.ToString(), GetType().Name);
                              _messageService.ShowErrorMessage(e.Message);
                          }
                      }
                      ));
        }

    }


    //public properties and propertychanged
    private void MainViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName.Equals("SelectTabIndex"))
        {
            SetCurrentViewModelCommand.Execute(SelectTabIndex);
        }
    }

    public int SelectTabIndex
    {
        get { return _selectTabIndex; }
        set { Set("SelectTabIndex", ref _selectTabIndex, value); }
    }

    public ViewModelBase CurrentViewModel
    {
        get { return _currentViewModel; }
        set { Set("CurrentViewModel", ref _currentViewModel, value); }
    }
Michael Gulik
  • 141
  • 11
  • 3
    You don't need this ugly "view-model to view converter". You define `DataTemplate`s for your view-models instead. – dymanoid Oct 25 '17 at 13:24
  • DataTemplates are definitely the way to go. You specify the DataType to be your view model. Tab controls are ContentControls, so you can actually create a collection of different view models, one for each tab, and bind that to the ItemsSource property. It'll pick the right DataTemplate for each. You can even track the current tab using SelectedItem. It's a really smooth workflow. –  Oct 25 '17 at 15:18
  • @Will does the answer at https://stackoverflow.com/questions/37109760/wpf-mvvm-setting-datacontext-of-tab-views detail what you are saying? – Michael Gulik Oct 25 '17 at 15:29
  • Yup, that's it. –  Oct 25 '17 at 16:09

0 Answers0