none
Livetでの画面遷移でちらつかない方法 RRS feed

  • 質問

  • 下記のコーディングで画面遷移しているのですが、window.Hide()をしてから遷移しますので、今のwindowが隠れる為に、なにもない状態となって、次に遷移先のwindowが開きます。よってちらつきが発生してしまいます。

    ちらつきの回避と思ってwindow.Hide()を画面遷移後(Messenger.Raise()の後)にすると制御が戻っていない為に、遷移元のwindowも残ってしまいます。

    遷移元のwindowが残らずに画面遷移する方法を教えて下さい。

    // 現在の View のインスタンスを取得
    var window = Application.Current.Windows.OfType<Window>().SingleOrDefault((w) => w.IsActive);
    try
    {
           // 現在の View を非表示
           window.Hide();
           // View にメッセージを送信~子画面をモーダルで起動
          Messenger.Raise(new TransitionMessage(new ViewModel2(), "ShowCommand2"));   

    }

    finally
     {
            // View を再表示する
            window.ShowDialog();
    }

    2015年9月11日 3:02

回答

  • Livetの流儀はしらないので適当

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
            xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" 
            xmlns:app="clr-namespace:WpfApplication1"
            Title="MainWindow" WindowState="Maximized">
        <i:Interaction.Triggers>
            <l:InteractionMessageTrigger 
                MessageKey="ShowCommand2" Messenger="{Binding Messenger}">
                <l:TransitionInteractionMessageAction
                    WindowType="{x:Type app:SubWindow}" Mode="Modal"/>
            </l:InteractionMessageTrigger>
        </i:Interaction.Triggers>
        <UniformGrid Columns="2">
            <Button Command="{Binding Path=TestCommand1}" Content="Test1"/>
            <Button Command="{Binding Path=TestCommand2}" Content="Test2"/>
        </UniformGrid>
    </Window>
    <Window x:Class="WpfApplication1.SubWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
            Title="SubWindow" WindowState="Maximized" >
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Loaded">
                <i:InvokeCommandAction Command="{Binding Path=Loaded}" 
                                       CommandParameter="{Binding Mode=OneTime,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>
            </i:EventTrigger>
            
            <i:EventTrigger EventName="Closing">
                <i:InvokeCommandAction Command="{Binding Path=Closing}"
                                       CommandParameter="{Binding Mode=OneTime,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Window>
    
    using System.Linq;
    using System.Windows;
    using System.Windows.Input;
    using Livet.Messaging;
    
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new MainViewModel();
            }
        }
    
        public partial class SubWindow : Window
        {
            public SubWindow()
            {
                InitializeComponent();
                System.Threading.Thread.Sleep(3000);
            }
        }
    
        class MainViewModel : Livet.ViewModel
        {
            public ICommand TestCommand1
            {
                get { return new Livet.Commands.ViewModelCommand(Test1); }
            }
            public ICommand TestCommand2
            {
                get { return new Livet.Commands.ViewModelCommand(Test2); }
            }
    
            public void Test1()
            {
                var window = Application.Current.Windows.OfType<Window>().SingleOrDefault((w) => w.IsActive);
                window.Hide();
                Messenger.Raise(new TransitionMessage(new ViewModel2(), "ShowCommand2"));
                window.Show();
            }
            public void Test2()
            {
                Messenger.Raise(new TransitionMessage(new ViewModel2() { NeedHideOwner = true }, "ShowCommand2"));
            }
        }
    
        class ViewModel2 : Livet.ViewModel
        {
            public ViewModel2()
            {
                Loaded = new Livet.Commands.ListenerCommand<Window>((w) =>
                    {
                        if (NeedHideOwner && w.Owner != null && w.Owner.Visibility == Visibility.Visible)
                        {
                            w.Owner.Hide();
                        }
                    });
    
                Closing = new Livet.Commands.ListenerCommand<Window>((w) =>
                    {
                        if (NeedHideOwner && w.Owner != null)
                        {
                            w.Owner.Show();
                        }
                    });
            }
    
            public bool NeedHideOwner { get; set; }
            public ICommand Loaded { get; private set; }
            public ICommand Closing { get; private set; }
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク 星 睦美 2015年9月18日 7:35
    2015年9月12日 13:26

すべての返信

  • Livetの流儀はしらないので適当

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
            xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" 
            xmlns:app="clr-namespace:WpfApplication1"
            Title="MainWindow" WindowState="Maximized">
        <i:Interaction.Triggers>
            <l:InteractionMessageTrigger 
                MessageKey="ShowCommand2" Messenger="{Binding Messenger}">
                <l:TransitionInteractionMessageAction
                    WindowType="{x:Type app:SubWindow}" Mode="Modal"/>
            </l:InteractionMessageTrigger>
        </i:Interaction.Triggers>
        <UniformGrid Columns="2">
            <Button Command="{Binding Path=TestCommand1}" Content="Test1"/>
            <Button Command="{Binding Path=TestCommand2}" Content="Test2"/>
        </UniformGrid>
    </Window>
    <Window x:Class="WpfApplication1.SubWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
            Title="SubWindow" WindowState="Maximized" >
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Loaded">
                <i:InvokeCommandAction Command="{Binding Path=Loaded}" 
                                       CommandParameter="{Binding Mode=OneTime,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>
            </i:EventTrigger>
            
            <i:EventTrigger EventName="Closing">
                <i:InvokeCommandAction Command="{Binding Path=Closing}"
                                       CommandParameter="{Binding Mode=OneTime,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Window>
    
    using System.Linq;
    using System.Windows;
    using System.Windows.Input;
    using Livet.Messaging;
    
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new MainViewModel();
            }
        }
    
        public partial class SubWindow : Window
        {
            public SubWindow()
            {
                InitializeComponent();
                System.Threading.Thread.Sleep(3000);
            }
        }
    
        class MainViewModel : Livet.ViewModel
        {
            public ICommand TestCommand1
            {
                get { return new Livet.Commands.ViewModelCommand(Test1); }
            }
            public ICommand TestCommand2
            {
                get { return new Livet.Commands.ViewModelCommand(Test2); }
            }
    
            public void Test1()
            {
                var window = Application.Current.Windows.OfType<Window>().SingleOrDefault((w) => w.IsActive);
                window.Hide();
                Messenger.Raise(new TransitionMessage(new ViewModel2(), "ShowCommand2"));
                window.Show();
            }
            public void Test2()
            {
                Messenger.Raise(new TransitionMessage(new ViewModel2() { NeedHideOwner = true }, "ShowCommand2"));
            }
        }
    
        class ViewModel2 : Livet.ViewModel
        {
            public ViewModel2()
            {
                Loaded = new Livet.Commands.ListenerCommand<Window>((w) =>
                    {
                        if (NeedHideOwner && w.Owner != null && w.Owner.Visibility == Visibility.Visible)
                        {
                            w.Owner.Hide();
                        }
                    });
    
                Closing = new Livet.Commands.ListenerCommand<Window>((w) =>
                    {
                        if (NeedHideOwner && w.Owner != null)
                        {
                            w.Owner.Show();
                        }
                    });
            }
    
            public bool NeedHideOwner { get; set; }
            public ICommand Loaded { get; private set; }
            public ICommand Closing { get; private set; }
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク 星 睦美 2015年9月18日 7:35
    2015年9月12日 13:26
  • gekkaさん。返信有難うございました。早速、コーディングをして動かしてみました。

    ちらつかずに画面遷移はしました。

    • 編集済み beluran 2015年9月14日 2:51
    • 回答の候補に設定 星 睦美 2015年9月15日 2:37
    • 回答の候補の設定解除 星 睦美 2015年9月18日 7:35
    2015年9月14日 2:50