我对Prism 6相对较新,并且已经查看了其他stackoverflow帖子,试图找到我的问题的答案。我有一个视图模块构造函数,每次导航到页面时都会执行。
在bootstrap文件的ConfigureContainer函数中,我有以下声明:
base.ConfigureContainer();
//Container.RegisterInstance<JobList>(new JobList());
Container.RegisterTypeForNavigation<JobList>("JobList");
使用JobList的Container.RegisterInstance函数似乎没什么区别。
JobList视图的顶部如下所示:
<UserControl x:Class="JobListModule.Views.JobList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:prism="http://prismlibrary.com/"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
prism:ViewModelLocator.AutoWireViewModel="True"
Width="1090" Height="900"
>
<i:Interaction.Triggers>
<prism:InteractionRequestTrigger SourceObject="{Binding ConfirmationRequest, Mode=OneWay}">
<prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True"/>
</prism:InteractionRequestTrigger>
</i:Interaction.Triggers>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70*"/>
<RowDefinition Height="830*"/>
</Grid.RowDefinitions>
<Grid Row="0" OpacityMask="#FFEEEBEB" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="83*"/>
<ColumnDefinition Width="37*"/>
</Grid.ColumnDefinitions>
<Label x:Name="JobListLabel" Grid.Column="0" Content="{x:Static p:Resources.JobListBuildListLabelText}" HorizontalAlignment="Center" VerticalAlignment="Center" Width="613" FontSize="48" Margin="67,-2,74,2" Height="70" RenderTransformOrigin="1.695,0.222" FontWeight="Bold" Padding="0" Grid.IsSharedSizeScope="True" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
<Button x:Name="AddJobFileBtn" Command="{Binding AddJobBtnClickedCommand}" Grid.Column="1" Content="{x:Static p:Resources.JobListAddBuildFileBtnText}" HorizontalAlignment="Center" Margin="56,10,64,11" VerticalAlignment="Center" Width="216" Height="49" RenderTransformOrigin="0.203,-0.173" FontSize="32" FontWeight="Bold" Padding="0">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBEC9CF"/>
<GradientStop Color="#FF5EB4C7" Offset="0.936"/>
<GradientStop Color="#FFC9E9F0" Offset="0.319"/>
</LinearGradientBrush>
</Button.Background>
</Button>
</Grid>
<ListBox x:Name="BuildList" Grid.Row="1" Margin="0,0,0,0" ItemsSource="{Binding Path=JobFileInfoList}" SelectedIndex="{Binding Path=JobListSelectedItemIndex, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="114*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="750"/>
<ColumnDefinition Width="100*"/>
<ColumnDefinition Width="200*"/>
</Grid.ColumnDefinitions>
<Label x:Name="JobFileNameLabel" Grid.Column="0" Content="{Binding JobFileName}" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="24" FontWeight="Bold" Padding="0"/>
<dx:SimpleButton Command="{Binding DataContext.LoadJobBtnClickedCommand,RelativeSource={RelativeSource AncestorType=ListBox}}" CommandParameter="{Binding JobFileName}" Grid.Column="1" Content="{x:Static p:Resources.JobListPrintBtnLabelText}" HorizontalAlignment="Center" Margin="25,19,23,25" VerticalAlignment="Center" Width="120" Height="60" RenderTransformOrigin="0.203,-0.173" FontSize="32" FontWeight="Bold" Padding="0"/>
<dx:SimpleButton Command="{Binding DataContext.TrashCanBtnClickedCommand,RelativeSource={RelativeSource AncestorType=ListBox}}" CommandParameter="{Binding JobFileName}" Grid.Column="2" Margin="0" BorderThickness="0" HorizontalAlignment="Center" Width="86" Height="86" VerticalAlignment="Center" Padding="0" Background="{x:Null}">
<Image Source="..\ButtonImages\TrashCan-64.png" />
</dx:SimpleButton>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
和JobList.xaml.cs文件包含:
public partial class JobList
{
public JobList()
{
InitializeComponent();
}
}
JobList视图模型如下:
using Common.GatedEvents;
using CommonApp;
using Prism.Commands;
using Prism.Events;
using Prism.Interactivity.InteractionRequest;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using VulcanGUI.Services;
using VulcanGUI.Logging;
using VulcanGUI.DialogService;
using VulcanGUI.DialogService.ViewModels;
namespace VulcanGUI.JobListModule.ViewModels
{
public class JobListViewModel : BindableBase, IDescribe, IInteractionRequestAware, INavigationAware
{
private readonly IRegionManager _regionManager;
private readonly log4net.ILog _logger;
protected readonly IEventAggregator EventAggregator;
// Delete Job Queue AMX File Confirmation
public InteractionRequest<IConfirmation> ConfirmationRequest { get; private set; }
public InteractionRequest<INotification> ErrorNotification { get; private set; }
private bool _deleteJobConfirmationRequestResult;
private bool _printJobConfirmationRequestResult;
public DelegateCommand RaiseDeleteJobConfirmationCommand { get; private set; }
public DelegateCommand RaiseLoadJobConfirmationCommand { get; private set; }
public ICommand LoadJobErrorNotificationCommand { get; private set; }
private readonly IDialogService _openFileDialogService;
private readonly IJobListDataService _jobListDataService;
private string JobFilePath {get; set;}
public int JobListSelectedItemIndex { get; set; }
public Action FinishInteraction { get; set; }
private ObservableCollection<JobFileInfoItem> _jobFileInfoList;
public ObservableCollection<JobFileInfoItem> JobFileInfoList
{
get { return _jobFileInfoList; }
set { _jobFileInfoList = value; }
}
public JobListViewModel(IRegionManager regionManager,
ILog4NetLogger logger,
IDialogService openFileDialogSvc,
IJobListDataService jobListDataSvc,
IEventAggregator eventAggregator
)
{
_regionManager = regionManager;
EventAggregator = eventAggregator;
ConfirmationRequest = new InteractionRequest<IConfirmation>();
ErrorNotification = new InteractionRequest<INotification>();
RaiseDeleteJobConfirmationCommand = new DelegateCommand(RaiseDeleteJobFromListConfirmation);
RaiseLoadJobConfirmationCommand = new DelegateCommand(RaiseLoadJobConfirmation);
LoadJobErrorNotificationCommand = new RelayCommand(LoadJobErrorNotification);
_openFileDialogService = openFileDialogSvc;
_jobListDataService = jobListDataSvc;
_logger = logger.GetLog4NetLogger();
AppEvents.MachineStatus.Event += MachineStatusHandler;
AppEvents.JobFileReady.Event += JobFileReadyHandler;
LoadJobFileInfoList();
}
public JobListViewModel() { }
public string Describe(string preface = "")
{
return preface + " JobListViewModel";
}
public log4net.ILog log
{
get { return _logger; }
}
private void LoadJobErrorNotification(object errMsg)
{
//var vm = new ErrorDialogViewModel((string)errMsg);
var vm = new ErrorDialogViewModel() {Message = (string) errMsg};
var result = DialogService.DialogService.OpenDialog(vm);
}
protected void JobFileReadyHandler(Object sender, GatedEventBase thisEvent, JobReadyArgs args)
{
Application.Current.Dispatcher.Invoke(() => LoadJobErrorNotification(args.Error));
if (args.Error.Length != 0)
{
}
else
{
Application.Current.Dispatcher.Invoke(() => _regionManager.RequestNavigate("ViewsRegion", "BuildActivity", new NavigationParameters("Test")));
}
}
protected void MachineStatusHandler(Object sender, GatedEventBase thisEvent, MachineStatusArgs args)
{
if (args.Request)
{
//CommonEvents.Processor.AddTask(new TaskEvent(this, AppEvents.MachineStatus, new MachineStatusArgs(OperationState)));
}
}
private void LoadJobFileInfoList()
{
var jobFileInfoList = _jobListDataService.GetJobListFilePathData();
_jobFileInfoList = new ObservableCollection<JobFileInfoItem>();
foreach (string jobFile in jobFileInfoList)
{
_jobFileInfoList.Add(new JobFileInfoItem(jobFile));
}
}
#region AddJobToList
public ICommand AddJobBtnClickedCommand
{
get { return new DelegateCommand(AddJobBtnClickedMethod); }
//get { return new DelegateCommand<object>(LoadJobBtnClickedMethod, CanLoadJobBtnClickedMethodBeExecuted); }
}
private void AddJobBtnClickedMethod()
{
ShowOpenFileDialog();
}
public void ShowOpenFileDialog()
{
var settings = new OpenFileDialogSettings()
{
Title = "Select Job File",
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
Filter = "Build File ( *.amx; *.txt) |*.amx; *.txt"
};
if (_openFileDialogService.ShowOpenFileDialog(settings))
{
JobFilePath = settings.FileName;
// Does the JobFilePath already exist in the list?
if (_jobFileInfoList.Any(p => p.JobFileFullPath == JobFilePath))
{
// Since the path is already in the list, just show it as selected
JobListSelectedItemIndex = _jobFileInfoList.FindIndex(p => p.JobFileFullPath == JobFilePath);
}
else
{
// Add it to the list
_jobFileInfoList.Add(new JobFileInfoItem(JobFilePath));
//Persist the list items
List<string> jobFilePathInfo = JobInfoObsListToList();
_jobListDataService.SaveJobListFilePathData(jobFilePathInfo);
}
}
}
#endregion AddJobToList
#region DeleteJobFromList
private void RaiseDeleteJobFromListConfirmation()
{
// By invoking the Raise method we are raising the Raised event and triggering any InteractionRequestTrigger that
// is subscribed to it.
// As parameters we are passing a Confirmation, which is a default implementation of IConfirmation (which inherits
// from INotification) provided by Prism and a callback that is executed when the interaction finishes.
ConfirmationRequest.Raise(
new Confirmation { Content = "Remove this build file from the list?", Title = "Confirmation" },
c => { _deleteJobConfirmationRequestResult = c.Confirmed; });
}
public ICommand TrashCanBtnClickedCommand
{
get { return new DelegateCommand<object>(TrashCanBtnClickedMethod); }
}
private void TrashCanBtnClickedMethod(Object jobFileName)
{
RaiseDeleteJobFromListConfirmation();
if ( _deleteJobConfirmationRequestResult )
{
// Determine the index of the _jobFileInfoList item containing the filename
var listIndex = _jobFileInfoList.FindIndex(p => p.JobFileName == (string)jobFileName);
_jobFileInfoList.RemoveAt(listIndex);
var jobFilePathInfo = JobInfoObsListToList();
_jobListDataService.SaveJobListFilePathData(jobFilePathInfo);
}
}
List<string> JobInfoObsListToList()
{
var jobFilePaths = new List<string>();
foreach( JobFileInfoItem jobInfo in _jobFileInfoList )
{
jobFilePaths.Add(jobInfo.JobFileFullPath);
}
return jobFilePaths;
}
#endregion DeleteJobFromList
#region LoadJob
public ICommand LoadJobBtnClickedCommand
{
get { return new DelegateCommand<object>(LoadJobBtnClickedMethod); }
}
private void RaiseLoadJobConfirmation()
{
// By invoking the Raise method we are raising the Raised event and triggering any InteractionRequestTrigger that
// is subscribed to it.
// As parameters we are passing a Confirmation, which is a default implementation of IConfirmation (which inherits
// from INotification) provided by Prism and a callback that is executed when the interaction finishes.
ConfirmationRequest.Raise(
new Confirmation { Content = "Load this job file?", Title = "Confirmation" },
c => { _printJobConfirmationRequestResult = c.Confirmed; });
}
private void LoadJobBtnClickedMethod(Object jobFileName)
{
RaiseLoadJobConfirmation();
if (_printJobConfirmationRequestResult)
{
int listIndex = _jobFileInfoList.FindIndex(p => p.JobFileName == (string)jobFileName);
string jobId = Guid.NewGuid().ToString();
var args = new String2Args(jobId, _jobFileInfoList[listIndex].JobFileFullPath);
var s = Path.GetExtension(_jobFileInfoList[listIndex].JobFileFullPath);
if (s != null)
{
string extension = s.ToLower();
if (extension == ".txt")
CommonEvents.Processor.AddTask(new TaskEvent(this, AppEvents.TextDataFile, args));
else
CommonEvents.Processor.AddTask(new TaskEvent(this, AppEvents.AMXBuildFile, args));
}
}
}
#endregion LoadJob
//private bool CanLoadJobBtnClickedMethodBeExecuted(object context)
//{
// //this is called to evaluate whether FuncToCall can be called
// //for example you can return true or false based on some validation logic
// return true;
//}
public INotification Notification { get; set; }
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return false;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
navigationContext.Parameters.Add("PageFrom", ToString());
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
}
}
}
非常感谢任何帮助
答案 0 :(得分:0)
您正在使用INavigationAware
界面,而IsNavigationTarget
始终返回false。这就是造成这种情况的原因。
根据某些逻辑更改此值以返回true或false,或者让它始终返回true。或者,如果确实不需要,请完全删除INavigationAware
的使用。
如果视图或视图模型实现INavigationAware
接口,则在导航期间调用IsNavigationTarget
函数。如果返回true,则它使用视图或视图模型的现有实例(如果存在)。否则,它会创建一个新实例。
您可以使用传递给函数的NavigationContext
执行诸如检查Parameters
集合值之类的内容,或者根据这些值,通过返回true来使用现有实例,或者让应用程序通过返回false来创建视图/视图模型的新实例。