以编程方式调用WPF TargetedTriggerAction(Programmatically

2019-09-23 23:30发布

我从想调用/没有它连接到一个按钮调用第三方库TargetedTriggerAction。 我没有问题,得到它与按钮的工作,但我想这样做在应对一些非UI事件。

这里是动作的类的声明:

 public class MeasureAction : TargetedTriggerAction<Map>

这里是我的设置代码至今:

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

我希望能够做这样的事,但我知道调用保护:

measure.Invoke();

Answer 1:

要调用您的触发器动作,你需要一个触发!

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();


Answer 2:

是第三方类封了?

如果不是,“最佳”答案很可能是从派生您自己的类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);
}


Answer 3:

旧的职位,但可能会有帮助。 我不喜欢这

public class MyMeasureAction : MeasureAction
{
    public void Execute()
    {
        OnTargetChanged(null, (Map)TargetObject);
        Invoke(null);
    }
}

...

var mymeasure = new MyMeasureAction();
mymeasure.TargetObject = MyMap;
mymeasure.xxxx = xxxx
....
mymeasure.Execute();

所述OnTargetChanged()方法将初始化MeasureAction的内部地图



文章来源: Programmatically Call WPF TargetedTriggerAction