我有一个Prism 6.3 / Unity WPF应用程序,该应用程序将在启动后查找已安装的扫描仪,如果没有,则向用户显示一条消息。为了呈现此消息,我的Shell视图中有一个通常折叠的特殊区域:
Shell.xaml
<Grid Grid.ColumnSpan="3" Grid.RowSpan="3" Panel.ZIndex="2" Visibility="{Binding MessageVisibility}"
fade:VisibilityAnimation.AnimationType="Fade">
<Grid.RowDefinitions>
<RowDefinition Height="15*"/>
<RowDefinition Height="70*"/>
<RowDefinition Height="15*"/>
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Fill="{DynamicResource AccentColorBrush2}"/>
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="{x:Static local:RegionNames.PopUpRegionName}"/>
<Rectangle Grid.Row="2" Fill="{DynamicResource AccentColorBrush2}"/>
</Grid>
创建消息后,事件聚合器会触发这样的事件
_eventAggregator.GetEvent<ShowMessage>().Publish(message);
和ShellViewModel像这样监听此事件:
ShellViewModel构造函数和方法
_eventAggregator.GetEvent<ShowMessage>().Subscribe(ReceiveMessage);
public void ReceiveMessage(Models.Message message)
{
_regionManager.RequestNavigate(RegionNames.PopUpRegionName, "MessageView");
MessageVisibility = Visibility.Visible;
}
之后,将弹出消息区域,并向用户显示消息。
Bootstrapper:
public class Bootstrapper : UnityBootstrapper
{
public override void Run(bool runWithDefaultConfiguration)
{
base.Run(runWithDefaultConfiguration);
(Container.Resolve(typeof(ScanViewModel)) as ScanViewModel).InitializeTwain();
}
protected override System.Windows.DependencyObject CreateShell()
{
return Container.Resolve(typeof(Shell), "Shell") as DependencyObject;
}
protected override void InitializeShell()
{
base.InitializeShell();
var mainWindow = (Shell)this.Shell;
Application.Current.MainWindow = mainWindow;
mainWindow.Show();
}
protected override void ConfigureServiceLocator()
{
base.ConfigureServiceLocator();
Container.RegisterType<IEventAggregator, EventAggregator>(new ContainerControlledLifetimeManager());
Container.RegisterType<IMessageViewModel, MessageViewModel>(new ContainerControlledLifetimeManager());
Container.RegisterType<IFolderSelectionViewModel, FolderSelectionViewModel>(new ContainerControlledLifetimeManager());
Container.RegisterType<IRegionManager, RegionManager>(new ContainerControlledLifetimeManager());
var regionManager = Container.TryResolve<IRegionManager>();
regionManager.RegisterViewWithRegion(RegionNames.PopUpRegionName, typeof(Views.MessageView));
regionManager.RegisterViewWithRegion(RegionNames.PopUpRegionName, typeof(Views.FolderSelectionView));
}
}
ScanViewModel InitializeTwain()方法
public void InitializeTwain()
{
try
{
twain = new Twain(new WpfWindowMessageHook(Application.Current.MainWindow));
SelectedScanner = null;
Scanners = new ObservableCollection<string>();
for (int i = 0; i < twain.SourceNames.Count; i++)
{
Scanners.Add(twain.SourceNames[i]);
}
if (Scanners.Count > 0)
SelectedScanner = Scanners[0];
else
throw new TwainException();
twain.ScanningComplete += Twain_ScanningComplete;
twain.TransferImage += delegate (object sender, TransferImageEventArgs args)
{
if (args.Image != null)
{
resultImage = args.Image;
images.Add(resultImage);
}
};
canScan = true;
((DelegateCommand)ScanCommand).RaiseCanExecuteChanged();
}
catch (TwainException)
{
canScan = false;
((DelegateCommand)ScanCommand).RaiseCanExecuteChanged();
Message = new Models.Message("TwainException", "No TWAIN compatible scanner could be found.");
// _eventAggregator.GetEvent<ShowMessage>().Publish(message) gets called here
}
}
我的问题:
当我在引导程序的Run()方法中调用InitializeTwain()方法,并且应该向用户显示不存在扫描仪的消息时,不会显示PopupRegion,而是底层的ScanView。而且我无法在ScanView中单击任何内容,因此某些内容将其隐藏。
当我从引导程序的Run()方法中删除InitializeTwain()调用并创建一个调用它的按钮,并在应用程序加载后单击它时,该消息将正确显示。
我想念什么?
[尝试等待调用该方法,直到外壳窗口已加载,即不要覆盖Run
,而是为Loaded
中的InitializeShell
事件挂接事件处理程序:
protected override void InitializeShell()
{
base.InitializeShell();
var mainWindow = (Shell)this.Shell;
Application.Current.MainWindow = mainWindow;
mainWindow.Loaded += OnLoaded;
mainWindow.Show();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
var window = (Window)sender;
window.Loaded -= OnLoaded;
(Container.Resolve(typeof(ScanViewModel)) as ScanViewModel).InitializeTwain();
}