/// <summary> /// 起動後にモデルの動作を開始します。 /// NOTE: エントリポイント的に動作する /// </summary> private void Initialize(IMainWindow mainWindow) { string characterName = CommonSettingRecord.Load().CharacterName; CharacterSetting = CharacterSetting.Load(characterName); _characterOperator = new HarrietCharacterOperator( characterName, mainWindow, CharacterSetting.CharacterAppearance ); _scriptingOperator = new ScriptingOperator( characterName, mainWindow, _characterOperator.Character, CharacterSetting ); Observable.FromEventPattern <EventArgs>(_scriptingOperator, nameof(_scriptingOperator.Initialized)) .Take(1) .Subscribe(_ => _timer.Start()); Observable.FromEventPattern <EventArgs>(_scriptingOperator, nameof(_scriptingOperator.Closed)) .Take(1) .Subscribe(_ => mainWindow.Close()); _scriptingOperator.Start(); //タイマーは初期化スクリプトが読み終わってから稼働開始するのでここでは放置 //_timer.Start(); }
/// <summary>アプリケーションの終了時に別のキャラを起動する操作を予約します。</summary> /// <param name="newCharacterName">変更先のキャラクター名</param> /// <returns>変更予約に成功した場合はtrue、失敗した場合はfalse</returns> public static bool ReserveChangeCharacter(string newCharacterName) { bool isChangeValid = CheckChangeCharacterValidity(newCharacterName); if (!isChangeValid) { return(false); } var record = CommonSettingRecord.Load(); record.CharacterName = newCharacterName; record.Save(); //再起動を予約 Application.Current.Exit += (_, __) => { string thisExePath = Path.Combine( Environment.CurrentDirectory, "Harriet.exe" ); Process.Start(thisExePath); }; return(true); //NOTE: あくまで予約操作なのでアプリケーションの終了は呼び出し元にやらせる }
/* コマンド、プロパティの定義にはそれぞれ * * lvcom : ViewModelCommand * lvcomn : ViewModelCommand(CanExecute無) * llcom : ListenerCommand(パラメータ有のコマンド) * llcomn : ListenerCommand(パラメータ有のコマンド・CanExecute無) * lprop : 変更通知プロパティ(.NET4.5ではlpropn) * * を使用してください。 * * Modelが十分にリッチであるならコマンドにこだわる必要はありません。 * View側のコードビハインドを使用しないMVVMパターンの実装を行う場合でも、ViewModelにメソッドを定義し、 * LivetCallMethodActionなどから直接メソッドを呼び出してください。 * * ViewModelのコマンドを呼び出せるLivetのすべてのビヘイビア・トリガー・アクションは * 同様に直接ViewModelのメソッドを呼び出し可能です。 */ /* ViewModelからViewを操作したい場合は、View側のコードビハインド無で処理を行いたい場合は * Messengerプロパティからメッセージ(各種InteractionMessage)を発信する事を検討してください。 */ /* Modelからの変更通知などの各種イベントを受け取る場合は、PropertyChangedEventListenerや * CollectionChangedEventListenerを使うと便利です。各種ListenerはViewModelに定義されている * CompositeDisposableプロパティ(LivetCompositeDisposable型)に格納しておく事でイベント解放を容易に行えます。 * * ReactiveExtensionsなどを併用する場合は、ReactiveExtensionsのCompositeDisposableを * ViewModelのCompositeDisposableプロパティに格納しておくのを推奨します。 * * LivetのWindowテンプレートではViewのウィンドウが閉じる際にDataContextDisposeActionが動作するようになっており、 * ViewModelのDisposeが呼ばれCompositeDisposableプロパティに格納されたすべてのIDisposable型のインスタンスが解放されます。 * * ViewModelを使いまわしたい時などは、ViewからDataContextDisposeActionを取り除くか、発動のタイミングをずらす事で対応可能です。 */ /* UIDispatcherを操作する場合は、DispatcherHelperのメソッドを操作してください。 * UIDispatcher自体はApp.xaml.csでインスタンスを確保してあります。 * * LivetのViewModelではプロパティ変更通知(RaisePropertyChanged)やDispatcherCollectionを使ったコレクション変更通知は * 自動的にUIDispatcher上での通知に変換されます。変更通知に際してUIDispatcherを操作する必要はありません。 */ #endregion /// <summary>ビューモデルを初期化します。</summary> public MainWindowViewModel() { if (!Directory.Exists(DirectoryNames.CharacterDirectory)) { AvailableCharacters = new MenuItem[] { }; } else { var displayedNames = DirectoryNames.GetAvailableDisplayNames(); //CF: ココで初期化する以外のシナリオとしてはモデルから文字列リスト付きのイベントが投げられるパターンなどがあり得る。 //TODO: Validなキャラだけ通すように直した方がいいとおもいまーす! AvailableCharacters = DirectoryNames.AvailableCharacters .Select(n => new MenuItem { Header = displayedNames[n], Command = new ActionCommand(() => OnCharacterSelected(n)) }) .ToArray(); } Topmost = CommonSettingRecord.Load().Topmost; }