カテゴリー別アーカイブ: MVVM

【MVVM】 コード・ビハインド(C#コード)で、ビヘイビア(Behavior)を設定するには

◆ C# Code

//<i:Interaction.Behaviors>
//    <localInteractivity:InvokeMethodBehavior 
// Target="{Binding DataContext, ElementName=Self}" MethodName="CreateUser"/>
//</i:Interaction.Behaviors>
var action = new System.Windows.Interactivity.InvokeCommandAction();
var methodBehavior = new Actions.InvokeMethodBehavior(); // Behavior
methodBehavior.MethodName = "CreateUser";
methodBehavior.Attach(button1);
System.Windows.Interactivity.Interaction.GetBehaviors(button1)
    .Add(methodBehavior);

◆ Behavior

using System;
using System.Windows;
using System.Windows.Controls;
// Expression Blend SDKをインストールし、
// System.Windows.Interactivity.dll を参照設定
// http://www.microsoft.com/downloads/ja-jp/details.aspx?displaylang=ja&FamilyID=d197f51a-de07-4edf-9cba-1f1b4a22110d
using System.Windows.Interactivity;
using System.Reflection;
using System.ComponentModel.Composition;

namespace Actions
{
    public class InvokeMethodBehavior : Behavior<UserControl>
    {
        public InvokeMethodBehavior()
        {
        }

        private static readonly DependencyProperty TargetProperty =
           DependencyProperty.Register("Target", typeof(object), 
               typeof(InvokeMethodBehavior), null);

        public object Target
        {
            get { return (object)GetValue(TargetProperty); }
            set { SetValue(TargetProperty, value); }
        }

        public string MethodName { get; set; }

        // 要素にアタッチされたときの処理。
        protected override void OnAttached()
        {
            base.OnAttached();
            this.AssociatedObject.LoadedNext += LayoutRootLoaded;
        }

        // 要素にデタッチされたときの処理。
        protected override void OnDetaching()
        {
            base.OnDetaching();
            this.AssociatedObject.LoadedNext -= LayoutRootLoaded;
        }
        
        // LayoutRootLoaded 時に実行されるメソッド。
        private void LayoutRootLoaded
            (object sender, EventArgs e)
        {            
            object InvokeObj;
            Type targetType;
            
            if (this.Target != null)
            {
                targetType = this.Target.GetType();
                InvokeObj = this.Target;
            }
            else
            {
                var root = this.AssociatedObject.Content as FrameworkElement;

                if (root == null)
                {
                    throw new ArgumentNullException("root");
                }
                else if (root.DataContext == null)
                {
                    throw new ArgumentNullException("DataContext");
                }

                targetType = root.DataContext.GetType();
                InvokeObj = root.DataContext;
            }

            if (string.IsNullOrWhiteSpace(this.MethodName))
            {
                throw new ArgumentNullException("MethodName");
            }

            MethodInfo method = targetType.GetMethod(this.MethodName
                , BindingFlags.Public | BindingFlags.Instance);
            
            if (method == null)
            {
                throw new InvalidOperationException
                    (String.Format("TargetMethodNotFound", this.MethodName));
            }

            method.Invoke(InvokeObj, null);
        }
    }
}

【MVVM】 コード・ビハインド(C#コード)で、イベント・トリガー(EventTrigger)を設定するには

◆ C# Code

//<i:Interaction.Triggers>
//    <i:EventTrigger EventName="Click">
//        <localInteractivity:InvokeMethodAction 
//          Target="{Binding DataContext, ElementName=Self}"
//          MethodName="CreateUser"/>
//    </i:EventTrigger>
//</i:Interaction.Triggers>
var clickTrigger = new System.Windows.Interactivity.EventTrigger("Click");
var action = new System.Windows.Interactivity.InvokeCommandAction();
var ma = new Actions.InvokeMethodAction(); // TriggerAction
ma.Target = this.DataContext;
ma.MethodName = "CreateUser";
clickTrigger.Actions.Add(ma);
System.Windows.Interactivity.Interaction
    .GetTriggers(button1).Add(clickTrigger);

◆ TriggerAction

using System;
using System.Windows;
// Expression Blend SDKをインストールし、
// System.Windows.Interactivity.dll を参照設定
// http://www.microsoft.com/downloads/ja-jp/details.aspx?displaylang=ja&FamilyID=d197f51a-de07-4edf-9cba-1f1b4a22110d
using System.Windows.Interactivity;
using System.Reflection;
using System.Windows.Controls.Primitives;

namespace Actions
{
    public class InvokeMethodAction : TriggerAction<FrameworkElement>
    {
        public InvokeMethodAction()
        {
        }

        private static readonly DependencyProperty TargetProperty =
            DependencyProperty.Register("Target", typeof(object),
                typeof(InvokeMethodAction), null);

        public object Target
        {
            get { return (object)GetValue(TargetProperty); }
            set { SetValue(TargetProperty, value); }
        }

        public string MethodName { get; set; }

        protected override void Invoke(object parameter)
        {
            if (this.Target == null)
            {
                throw new ArgumentNullException("Target");
            }

            if (string.IsNullOrWhiteSpace(this.MethodName))
            {
                throw new ArgumentNullException("MethodName");
            }
            
            Type targetType = this.Target.GetType();
            MethodInfo method = targetType.GetMethod(this.MethodName
                , BindingFlags.Public | BindingFlags.Instance);
            
            if (method == null)
            {
                throw new InvalidOperationException(
                    String.Format("TargetMethodNotFound", this.MethodName));
            }
            method.Invoke(this.Target, null);
        }
    }
}

【MVVM】 コード・ビハインド(C#コード)で、バインディング(Binding)を設定するには

◆ C# Code

// <TextBox Name="textBox1" Text="{Binding Path=FirstName, Mode=TwoWay}" />
Binding bi = new Binding("FirstName");
bi.Mode = BindingMode.TwoWay;
textBox1.SetBinding(TextBox.TextProperty, bi);


// <TextBlock Name="textBox1" Text="{Binding Path=Birthday
//     , Converter={StaticResource TestConverter}
//     , ConverterParameter=yyyyMMdd}"/> 
Binding bi = new Binding("Birthday");
bi.Mode = BindingMode.TwoWay;
bi.Converter = NumericFormatConverter // IValueConverter
bi.ConverterParameter = "yyyyMMdd";
textBox1.SetBinding(TextBox.TextProperty, bi);


// <Button Name="button1" Command="{Binding Path=TestCommand, Mode=OneWay}" />
Binding bi = new Binding("TestCommand");
bi.Mode = BindingMode.OneWay;
button1.SetBinding(Button.CommandProperty, bi);

◆ IValueConverter

using System;
using System.Windows.Data;
using System.Globalization;

public class NumericFormatConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        string ret = "0";
        if (value != null && IsNumeric(value))
        {
            ret = ((decimal)value).ToString(parameter);
        }
        return ret;
    }

    public static bool IsNumeric(object value)
    {
        decimal ret;
        return decimal.TryParse(value.ToString()
            , NumberStyles.Any, null, out ret);
    }

    public object ConvertBack(object value, Type targetType
        , object parameter, CultureInfo culture)
    {
        decimal ret = 0m;
        decimal.TryParse(value.ToString(), NumberStyles.Any, null, out ret);
        return ret;
    }
}

【MVVM】ViewModel から View へメッセージを送信するには

◆ 事前準備

★MVVM Light Toolkitを使用する
・NuGet
  http://nuget.org/List/Packages/MvvmLight
・インストーラー
  http://mvvmlight.codeplex.com/

◆ Messenger

using GalaSoft.MvvmLight.Messaging;

namespace Common.MvvmLight
{
    public static class MessengeInstance
    {
        private static Messenger _messenger = new Messenger();

        public static Messenger Messenger
        {
            get { return _messenger; }
        }
    }
}

◆ ViewModel(メッセージ送信)

using GalaSoft.MvvmLight.Messaging;
using Common.MvvmLight;

namespace ViewModels
{
    public class TestViewModel
    {
        // --省略--

        // メッセージを送信
        private void SendMessage()
        {
            // NotificationMessageで String型のメッセージを送信
            MessengeInstance.Messenger.Send<NotificationMessage>
                (new NotificationMessage("NotificationMessage"));

            // GenericMessageで、任意の型のメッセージを送信
            MessengeInstance.Messenger.Send<GenericMessage<string>>
                (new GenericMessage<string>("GenericMessage"));
        }
    }
}

◆ View(メッセージ受信)

using GalaSoft.MvvmLight.Messaging;
using Common.MvvmLight;

namespace Views
{
    public class TestView
    {
        // --省略--

        // メッセージを受信
        private void ReceiveMessage()
        {
            // NotificationMessageで String型のメッセージを受信
            MessengeInstance.Messenger.Register<NotificationMessage>
                (this, msg => MessageBox.Show(msg.Notification));

            // GenericMessageで 任意の型のメッセージを受信
            MessengeInstance.Messenger.Register<GenericMessage<string>>
                (this, msg => MessageBox.Show(msg.Content));
        }
    }
}

【MVVM】 Bindingしたプロパティの値を変換するには

【MVVM】 Bindingしたプロパティの値を変換するには

// コンバートクラス
public class TestConverter : IValueConverter 
{
    public object Convert( object value, Type targetType
        , object parameter, CultureInfo culture )
    {
        ...
    }

    public object ConvertBack( object value, Type targetType
        , object parameter, CultureInfo culture )
    {
        ...
    }
}

// Xamlで記述した場合
<TextBlock Text="{Binding [DependencyPropertyName]
    , Converter={StaticResource [IValueConverter] }
    , ConverterParameter = [parameter] }"/> 

// C#で記述した場合
Binding binding = new Binding( [DependencyPropertyName] );
binding.Source = 
binding.Converter = [IValueConverter];
binding.ConverterParameter = [parameter];

// 参考サイト
// Q042. DataGrid のセルの値を書式設定したいのですが・・・
http://d.hatena.ne.jp/hilapon/20110218/1298009605