LoginSignup
0
2

More than 5 years have passed since last update.

C# > Visual Studio 2017 でLivetを試してみた

Posted at

概要

Livet初学者です。Visual Studio 2017にLivetを入れてMVVMの形でHelloWorldを書いてみました。
これでいいのか全く自信がありません。

コード

MainWindow.xaml
<Window x:Class="LivetHelloApplication.Views.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:ei="http://schemas.microsoft.com/expression/2010/interactions"
        xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"
        xmlns:v="clr-namespace:LivetHelloApplication.Views"
        xmlns:vm="clr-namespace:LivetHelloApplication.ViewModels"
        Title="Livetサンプル:挨拶" Height="350" Width="525">

    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>

    <i:Interaction.Triggers>

        <!--Viewに特別な要件が存在しない限りは、トリガーやアクションの自作にこだわらず積極的にコードビハインドを使いましょう -->
        <!--Viewのコードビハインドは、基本的にView内で完結するロジックとViewModelからのイベントの受信(専用リスナを使用する)に限るとトラブルが少なくなります -->
        <!--Livet1.1からはコードビハインドでViewModelのイベントを受信するためのWeakEventLisnterサポートが追加されています -->

        <!--WindowのContentRenderedイベントのタイミングでViewModelのInitializeメソッドが呼ばれます-->
        <i:EventTrigger EventName="ContentRendered">
            <l:LivetCallMethodAction MethodTarget="{Binding}" MethodName="Initialize"/>
        </i:EventTrigger>

        <!--Windowが閉じたタイミングでViewModelのDisposeメソッドが呼ばれます-->
        <i:EventTrigger EventName="Closed">
            <l:DataContextDisposeAction/>
        </i:EventTrigger>

        <!--WindowのCloseキャンセル処理に対応する場合は、WindowCloseCancelBehaviorの使用を検討してください-->

    </i:Interaction.Triggers>

    <Grid FocusManager.FocusedElement="{Binding ElementName=textBox}">
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Margin="10,10,0,0" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
        <Button x:Name="button" Content="こんにちは!" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="135,13,0,0" IsDefault="True" Command="{Binding OutputHelloMessageCommand, Mode=OneWay}"/>
        <TextBlock x:Name="textBlock" TextWrapping="Wrap" VerticalAlignment="Top" Margin="10,38,10,0" Text="{Binding HelloMessage}"/>
    </Grid>
</Window>
MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Livet;
using Livet.Commands;
using Livet.Messaging;
using Livet.Messaging.IO;
using Livet.EventListeners;
using Livet.Messaging.Windows;

using LivetHelloApplication.Models;

namespace LivetHelloApplication.ViewModels
{
    public class MainWindowViewModel : ViewModel
    {
        /* コマンド、プロパティの定義にはそれぞれ 
         * 
         *  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を操作する必要はありません。
         */

        private Model model = new Model();
        private PropertyChangedEventListener listener;

        public void Initialize()
        {
            listener = new PropertyChangedEventListener(model);
            listener.RegisterHandler(HelloMessageChanged);
        }

        private void HelloMessageChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case nameof(model.HelloMessage):
                    HelloMessage = model.HelloMessage;
                    break;
                case nameof(model.Name):
                    Name = model.Name;
                    break;
                default:
                    break;
            }
        }

        #region HelloMessage変更通知プロパティ
        private string _HelloMessage = string.Empty;

        public string HelloMessage
        {
            get
            { return _HelloMessage; }
            set
            { 
                if (_HelloMessage == value)
                    return;
                _HelloMessage = value;
                model.HelloMessage = _HelloMessage;
                RaisePropertyChanged();
            }
        }
        #endregion

        #region Name変更通知プロパティ
        private string _Name = string.Empty;

        public string Name
        {
            get
            { return _Name; }
            set
            { 
                if (_Name == value)
                    return;
                _Name = value;
                model.Name = _Name;
                RaisePropertyChanged();
            }
        }
        #endregion

        #region OutputHelloMessageCommand
        private ListenerCommand<string> _OutputHelloMessageHelloCommand;

        public ListenerCommand<string> OutputHelloMessageCommand
        {
            get
            {
                if (_OutputHelloMessageHelloCommand == null)
                {
                    _OutputHelloMessageHelloCommand = new ListenerCommand<string>(OutputHelloMessage);
                }
                return _OutputHelloMessageHelloCommand;
            }
        }

        public void OutputHelloMessage(string parameter)
        {
            model.Hello();
        }
        #endregion
    }
}
Model.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Livet;

namespace LivetHelloApplication.Models
{
    public class Model : NotificationObject
    {
        #region HelloMessage変更通知プロパティ
        private string _HelloMessage = string.Empty;

        public string HelloMessage
        {
            get
            { return _HelloMessage; }
            set
            { 
                if (_HelloMessage == value)
                    return;
                _HelloMessage = value;
                RaisePropertyChanged();
            }
        }
        #endregion

        #region Name変更通知プロパティ
        private string _Name = string.Empty;

        public string Name
        {
            get
            { return _Name; }
            set
            { 
                if (_Name == value)
                    return;
                _Name = value;
                RaisePropertyChanged();
            }
        }
        #endregion

        public void Hello()
        {
            HelloMessage = Name != "" ? $"{Name}さん、こんにちは!" : string.Empty;
        }
    }
}
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2