2

特定の条件に基づいて、表示されているビューを切り替える必要があります。ViewModelのコンストラクターに切り替えロジックを実装しました

View と ViewModel の新しいインスタンスを常に取得できるように、 Viewに実装IRegionMemberLifetimeして設定しています。KeepAlivefalse

しかし、何らかの理由で、Navigation Buttonをクリックすると、ブレークポイントKeepAliveが到達せず、 WelcomeViewではなく MainView が取得されます。

参照用のコードは次のとおりです。

ナビゲーション ボタン:

<Controls:SignedButton VerticalAlignment="Top" Width="275" Height="45"
    Foreground="#FFFFFF" 
    LeftSign="&lt;" 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; }
    }
}

シェル ビュー モデル:

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; }
}
4

1 に答える 1

0

Prism Library の RegionMemberLifetimeBehavior クラスを調べると便利です (私にとっては、C:\Prism4\PrismLibrary\Desktop\Prism\Regions\Behaviors にあります)。

IRegionMemberLifetime インターフェイスと 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 プロパティがヒットしていない場合、それは ActiveViews から削除されていません。また、IoC を介してコンテナーからビューを解決する場合は、ビューをシングルトン タイプとして登録していないこと (解決されるたびに新しいインスタンスを取得すること) を確認してください。属性/インターフェースはリージョンから完全に削除するだけで、新しいインスタンスを取得することを保証するものではありません。

于 2012-10-09T18:19:43.577 に答える