4

ボタンにアタッチせずに呼び出し/呼び出したいサードパーティ ライブラリの TargetedTriggerAction があります。ボタンで動作させるのに問題はありませんが、UI 以外のイベントに応答して実行したいと考えています。

アクションのクラス宣言は次のとおりです。

 public class MeasureAction : TargetedTriggerAction<Map>

これまでのセットアップコードは次のとおりです。

    var measure = new MeasureAction();
    measure.TargetObject = _mapControl;
    measure.MeasureMode = MeasureAction.Mode.Polyline;
    measure.MapUnits = DistanceUnit.Miles;

このようなことができるようにしたいのですが、Invoke が保護されていることはわかっています。

measure.Invoke();
4

3 に答える 3

8

トリガー アクションを呼び出すには、トリガーが必要です。

namespace TriggerTest
{
    using System.Windows;

    /// <summary>
    /// A trigger that may be invoked from code.
    /// </summary>
    public class ManualTrigger : System.Windows.Interactivity.TriggerBase<DependencyObject>
    {
        /// <summary>
        /// Invokes the trigger's actions.
        /// </summary>
        /// <param name="parameter">The parameter value.</param>
        public void Invoke(object parameter)
        {
            this.InvokeActions(parameter);
        }
    }
}

上記は、UI の依存関係なしで呼び出すことができるトリガーの実装です。例えば:

var measure = new MeasureAction();
measure.TargetObject = _mapControl;
measure.MeasureMode = MeasureAction.Mode.Polyline;
measure.MapUnits = DistanceUnit.Miles; 

ManualTrigger trigger = new ManualTrigger();
trigger.Actions.Add(measure);
trigger.Invoke(null);

これをさらに簡単に呼び出すために、拡張メソッドを に追加できますTriggerAction

namespace TriggerTest
{
    using System.Windows.Interactivity;

    /// <summary>
    /// Allows a trigger action to be invoked from code.
    /// </summary>
    public static class TriggerActionExtensions
    {
        /// <summary>
        /// Invokes a <see cref="TriggerAction"/> with the specified parameter.
        /// </summary>
        /// <param name="action">The <see cref="TriggerAction"/>.</param>
        /// <param name="parameter">The parameter value.</param>
        public static void Invoke(this TriggerAction action, object parameter)
        {
            ManualTrigger trigger = new ManualTrigger();
            trigger.Actions.Add(action);

            try
            {
                trigger.Invoke(parameter);
            }
            finally
            {
                trigger.Actions.Remove(action);
            }
        }

        /// <summary>
        /// Invokes a <see cref="TriggerAction"/>.
        /// </summary>
        /// <param name="action">The <see cref="TriggerAction"/>.</param>
        public static void Invoke(this TriggerAction action)
        {
            action.Invoke(null);
        }
    }
}

これで、本当に欲しかったものを書くことができます:

var measure = new MeasureAction();
measure.TargetObject = _mapControl;
measure.MeasureMode = MeasureAction.Mode.Polyline;
measure.MapUnits = DistanceUnit.Miles; 
measure.Invoke();
于 2012-10-19T15:51:19.787 に答える
0

サードパーティのクラスは封印されていますか?

そうでない場合、「最良の」答えは、おそらく独自のクラスを派生させMeasureActionてインボーカーを追加することです(物事をきれいに保ちたい場合は、内部/保護してください)。

それが封印されている/そうでなければ凍結されている場合、おそらくリフレクションが最善の策です-キャッシュする方法や、この呼び出しのコストを高速化する方法がありますが、基本的なコードは次のようになります。

// Paste in the code in the original question here, name of instance == measure
var actionMethod = typeof(MeasureAction)
    .GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
    .FirstOrDefault(meth => meth.Name == "Invoke");
if(actionMethod != null)
{
    var result = actionMethod.Invoke(measure, null);
}
于 2012-10-16T17:02:26.403 に答える