我需要根据特定条件切换显示的 View 。
我已经在 ViewModel 的构造函数中实现了切换逻辑
我在 View 上实现IRegionMemberLifetime
并将KeepAlive
设置为false
,以便始终获得View和ViewModel的新实例。
但是由于某些原因,当我单击导航按钮时,我在KeepAlive
处的断点永远不会到达,并且我得到的是 MainView 而不是 WelcomeView 。
这是供您引用的代码:
导航按钮:
<Controls:SignedButton VerticalAlignment="Top" Width="275" Height="45"
Foreground="#FFFFFF"
LeftSign="<" Text="Back to Accounts"
TextSize="20" ButtonBackground="#666666"
HoverBackground="#0FBDAC" HoverOpacity="1" Margin="0,25,0,0"
Command="{x:Static Infrastructure:ApplicationCommands.NavigateCommand}"
CommandParameter="{x:Type Views:MainView}"/>
查看模型:
[RegionMemberLifetime(KeepAlive = false)]
public class MainViewModel : ViewModel, IMainViewModel
{
private readonly IUnityContainer _container;
private readonly IRegionManager _regionManager;
public MainViewModel(IUnityContainer container, IRegionManager regionManager)
{
_container = container;
_regionManager = regionManager;
Accounts = new List<Account>();
if (Accounts.Any()) return;
IRegion region = _regionManager.Regions[Regions.Main];
var views = region.Views;
foreach (var view in views)
{
region.Remove(view);
}
region.Add(_container.Resolve<IWelcomeView>());
}
public IList<Account> Accounts { get; private set; }
}
查看模型库:
public abstract class ViewModel : IViewModel
{
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
查看:
[RegionMemberLifetime(KeepAlive = false)]
public partial class MainView : UserControl, IMainView
{
public MainView(IMainViewModel mainViewModel)
{
InitializeComponent();
ViewModel = mainViewModel;
}
public IViewModel ViewModel
{
get { return (IViewModel) DataContext; }
set { DataContext = value; }
}
}
Shell View 模型:
public class ShellViewModel : ViewModel, IShellViewModel
{
private readonly IRegionManager _regionManager;
public ShellViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
NavigateCommand = new DelegateCommand<object>(Navigate);
ApplicationCommands.NavigateCommand.RegisterCommand(NavigateCommand);
}
private void Navigate(object navigatePath)
{
if (navigatePath != null)
{
_regionManager.RequestNavigate(Regions.Main, navigatePath.ToString());
}
}
public DelegateCommand<object> NavigateCommand { get; private set; }
}
最佳答案
在Prism库中查看RegionMemberLifetimeBehavior类对您很有用(对我来说,它位于C:\Prism4\PrismLibrary\Desktop\Prism\Regions\Behaviors)
IRegionMemberLifetime接口(interface)和RegionMemberLifetimeAttribute都可以完成相同的操作,并且可以在您的View或ViewModel上定义(前提是将ViewModel设置为DataContext)。
这是相关的代码:
private void OnActiveViewsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// We only pay attention to items removed from the ActiveViews list.
// Thus, we expect that any ICollectionView implementation would
// always raise a remove and we don't handle any resets
// unless we wanted to start tracking views that used to be active.
if (e.Action != NotifyCollectionChangedAction.Remove) return;
var inactiveViews = e.OldItems;
foreach (var inactiveView in inactiveViews)
{
if (!ShouldKeepAlive(inactiveView))
{
this.Region.Remove(inactiveView);
}
}
}
private static bool ShouldKeepAlive(object inactiveView)
{
IRegionMemberLifetime lifetime = GetItemOrContextLifetime(inactiveView);
if (lifetime != null)
{
return lifetime.KeepAlive;
}
RegionMemberLifetimeAttribute lifetimeAttribute = GetItemOrContextLifetimeAttribute(inactiveView);
if (lifetimeAttribute != null)
{
return lifetimeAttribute.KeepAlive;
}
return true;
}
我什至可以步进这些代码来查看它如何与我的应用程序交互。要回答您的问题,如果您的KeepAlive属性没有被击中,那么它不会从ActiveView中删除。还要确保,如果要通过IoC从容器解析 View ,则尚未将其注册为单例类型(每次解析时都会得到一个新实例)。属性/接口(interface)只会将其完全从区域中删除,不能保证您会获得一个新的实例。
关于wpf - WPF PRISM : IRegionMemberLifetime KeepAlive doesn't get called,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12774539/