Как вызывать функцию каждый раз, когда вы переходите на страницу, используя MVVMLight WPF - PullRequest
0 голосов
/ 24 октября 2018

Так вот мой сценарий.У меня есть страница, которая загружает список баз из базы данных.Если я перехожу на страницу, вызывается конструктор и вызывается моя функция LoadBases ().Это здорово, именно то, что мне нужно.

Проблема:

Если я отойду от страницы и добавлю еще несколько баз в базу данных с другой страницы,и затем вернитесь назад, конструктор не вызывается, поэтому новые базы не загружаются в мой список баз.

Что я пробовал:

Просмотр модели локатора в MVVMLight

public class ViewModelLocator
{
    static ViewModelLocator()
    {
        SetupNavigation();
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
        SimpleIoc.Default.Register<BomConfiguratorContext>();

        if (ViewModelBase.IsInDesignModeStatic)
        {
            SimpleIoc.Default.Register<IUnitOfWork, UnitOfWork>();
        }
        else
        {
            SimpleIoc.Default.Register<IUnitOfWork, UnitOfWork>();
        }

        //   SimpleIoc.Default.Register<MainViewModel>();
        SimpleIoc.Default.Register<LoginViewModel>();
        SimpleIoc.Default.Register<UserNavigationViewModel>();
        SimpleIoc.Default.Register<AddNewBasesViewModel>();
        SimpleIoc.Default.Register<AddNewBillOfMaterialsViewModel>();
        SimpleIoc.Default.Register<AddNewOptionsViewModel>();
        SimpleIoc.Default.Register<AddNewRulesViewModel>();
        SimpleIoc.Default.Register<GenerateBillOfMaterialsViewModel>();

    }

    /// <summary>
    /// Gets the Main property.
    /// </summary>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
        "CA1822:MarkMembersAsStatic",
        Justification = "This non-static member is needed for data binding purposes.")]

    public LoginViewModel LoginViewModel
    {
        get{ return ServiceLocator.Current.GetInstance<LoginViewModel>(); }
    }
    public UserNavigationViewModel ManageRulesViewModel
    {
        get { return ServiceLocator.Current.GetInstance<UserNavigationViewModel>(); }
    }
    public AddNewBasesViewModel AddNewBasesViewModel
    {
        get { return ServiceLocator.Current.GetInstance<AddNewBasesViewModel>(); }
    }
    public AddNewBillOfMaterialsViewModel AddNewBillOfMaterialsViewModel
    {
        get { return ServiceLocator.Current.GetInstance<AddNewBillOfMaterialsViewModel>(); }
    }
    public AddNewOptionsViewModel AddNewOptionsViewModel
    {
        get { return ServiceLocator.Current.GetInstance<AddNewOptionsViewModel>(); }
    }
    public AddNewRulesViewModel AddNewRulesViewModel
    {
        get
        {
            SimpleIoc.Default.Unregister<AddNewRulesViewModel>();
            SimpleIoc.Default.Register<AddNewRulesViewModel>();
            return ServiceLocator.Current.GetInstance<AddNewRulesViewModel>();
        }
    }
    public GenerateBillOfMaterialsViewModel GenerateBillOfMaterialsViewModel
    {
        get{return ServiceLocator.Current.GetInstance<GenerateBillOfMaterialsViewModel>();}
    }

    /// <summary>
    /// Cleans up all the resources.
    /// </summary>
    public static void Cleanup()
    {
    }

    private static void SetupNavigation()
    {
        SimpleIoc.Default.Unregister<INavigationService>();
        var navigationService = new FrameNavigationService();
        navigationService.Configure("LoginView", new Uri("/Views/LoginView.xaml", UriKind.Relative));
        navigationService.Configure("UserNavigationView", new Uri("/Views/UserNavigationView.xaml", UriKind.Relative));
        navigationService.Configure("AddNewBasesView", new Uri("/Views/Bases/AddNewBasesView.xaml", UriKind.Relative));
        navigationService.Configure("AddNewBillOfMaterialsView", new Uri("/Views/BillOfMaterials/AddNewBillOfMaterialsView.xaml", UriKind.Relative));
        navigationService.Configure("AddNewOptionsView", new Uri("/Views/Options/AddNewOptionsView.xaml", UriKind.Relative));
        navigationService.Configure("AddNewRulesViewStep1", new Uri("/Views/Rules/AddNewRules/AddNewRulesStep1.xaml", UriKind.Relative));
        navigationService.Configure("AddNewRulesViewStep2", new Uri("/Views/Rules/AddNewRules/AddNewRulesStep2.xaml", UriKind.Relative));
        navigationService.Configure("AddNewRulesViewStep3", new Uri("/Views/Rules/AddNewRules/AddNewRulesStep3.xaml", UriKind.Relative));
        navigationService.Configure("AddNewRulesViewStep4", new Uri("/Views/Rules/AddNewRules/AddNewRulesStep4.xaml", UriKind.Relative));
        navigationService.Configure("AddNewRulesViewStep5", new Uri("/Views/Rules/AddNewRules/AddNewRulesStep5.xaml", UriKind.Relative));
        navigationService.Configure("AddNewRulesViewStep6", new Uri("/Views/Rules/AddNewRules/AddNewRulesStep6.xaml", UriKind.Relative));
        navigationService.Configure("AddNewRulesViewStep7", new Uri("/Views/Rules/AddNewRules/AddNewRulesStep7.xaml", UriKind.Relative));
        navigationService.Configure("GenerateBillOfMaterialsView", new Uri("/Views/BillOfMaterials/GenerateBillOfMaterialsView.xaml", UriKind.Relative));
        SimpleIoc.Default.Register<INavigationService>(() => navigationService);
    }
}

Просмотр модели с использованием INavigationService

Просто пример того, как я внедряю службу навигации и использую ее для навигации по страницам.

public LoginViewModel(IUnitOfWork unitOfWork, INavigationService navService)
    {
        _UnitOfWork = unitOfWork;
        _NavigationService = navService;
        LoginCommand = new RelayCommand<IHavePassword>((IHavePassword parameter) => LoginAsync(parameter));
    }

Навигация на страницу

 private async void LoginAsync(IHavePassword parameter)
    {
       if( await Task<bool>.Run(() => Login(parameter)))
            _NavigationService.NavigateTo("UserNavigationView");

    }

Страница, на которую я перехожу

Это простопример того, как я использую контекст данных на странице.

<local:BasePage x:Class="YAI.BomConfigurator.Desktop.Views.UserNavigationView"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  xmlns:local="clr-namespace:YAI.BomConfigurator.Desktop"
  mc:Ignorable="d" 
  d:DesignHeight="600" d:DesignWidth="800"
  Title="UserNavigationView"
  DataContext="{Binding ManageRulesViewModel, Source={StaticResource Locator}}">

<Border>
    <Grid>
        <ScrollViewer>
            <StackPanel
                VerticalAlignment="Center"
                HorizontalAlignment="Center"
                TextBlock.TextAlignment="Center">
                <Border Background="{StaticResource BackgroundLightBrush}"
                        CornerRadius="10"
                        Padding="15 50 15 15"
                        Width="600"
                        Margin="50 50 50 0">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <TextBlock Grid.ColumnSpan="2" Text="I Would Like To..." 
                                   FontSize="{StaticResource FontSizeLarge}"
                                   FontFamily="{StaticResource LatoRegular}"
                                   Foreground="{StaticResource MediumBlueBrush}"
                                   Margin="0 0 0 15"/>
                        <StackPanel Grid.Column="0" Margin="0 0 25 0">

                            <Button Content="Generate BOMs"
                                Margin="0 50 0 20"
                                Command="{Binding GenerateBillOfMaterialsCommand}"/>
                            <Button Content="Check Rules"
                                    Margin="0 25 0 20"
                                    Command="{Binding CheckRulesCommand}"/>
                            <Button Content="Add New Options"
                                    Margin="0 25 0 20"
                                    Command="{Binding AddNewOptionsCommand}"/>
                        </StackPanel>
                        <StackPanel Grid.Column="1">
                            <Button Content="Add New BOMs"
                                    Margin="0 50 0 20"
                                    Command="{Binding AddNewBillOfMaterialsCommand}" />
                            <Button Content="Add New Rules"
                                    Margin="0 25 0 20"
                                    Command="{Binding AddNewRulesCommand}"/>
                            <Button Content="Add New Bases"
                                    Margin="0 25 0 20"
                                    Command="{Binding AddNewBasesCommand}"/>
                        </StackPanel>

                    </Grid>
                </Border>
            </StackPanel>
        </ScrollViewer>
    </Grid>
</Border>

Проблема с этим решением заключается в том, что при отмене регистрации и повторной регистрации модели представления при каждом ее вызове, когдаЯ перемещаюсь по моим представлениям, которые все используют datacontext AddNewRulesViewModel, это буквальновынимает все мои переменные и вызывает конструктор для КАЖДОЙ страницы (около 7 из них используют одну и ту же модель представления).

Итак, я ищу способ вызова только моей функции LoadBases ()когда я перехожу на определенную страницу.Кто-нибудь может дать мне несколько советов о том, как подойти к этому?

1 Ответ

0 голосов
/ 15 ноября 2018

Я решил проблему с помощью триггера событий на моем событии Page Loaded.Вот небольшой пример того, что я сделал.

Триггер в xaml

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <i:InvokeCommandAction Command="{Binding LoadAllDataCommand}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

Просмотр модели LoadAllDataCommand

LoadAllDataCommand = new RelayCommand(async () => await LoadAllDataAsync());

Команда просмотра модели Действие

 private async Task LoadAllDataAsync()
    {
        AllBases.Clear();
        try
        {
            using (var UOW = _UnitOfWorkFactory.Create())
            {
                foreach (Base ba in await Task.Run(() => _BaseRepository.GetAll()))
                {
                    AllBases.Add(ba);
                }
            }
        }
        catch (Exception)
        {
            await Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => {
                Messenger.Default.Send(new ToastErrorMessage { Message = "Error: There was a problem with loading the data" });
            }));
        }     
    }

Таким образом, при каждой загрузке страницы мои данные перезагружаются из базы данных со всеми вновь добавленными базами.

...