Hi Jason,
Sorry for the late reply. It has been a hectic week. I don’t know if you were able to figure it out on your own, but I have created a more complete example that illustrates how to handle updates when e.g. a new step is added to the test plan, or the test plan is reloaded. It also shows how to achieve GUI updates based on events, in addition to updating the GUI directly from the step.
Note that I don’t recommend creating such a strong coupling between your GUI and test steps.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Xml.Serialization;
using Keysight.OpenTap.Gui;
using Keysight.OpenTap.Wpf;
using OpenTap;
namespace WpfExample
{
public class MyTestStep : TestStep
{
[XmlIgnore]
internal MyDockPanel dockPanel { get; set; }
private string _textBlockText;
[XmlIgnore]
public string TextBlockText
{
get => _textBlockText;
set
{
if (value == _textBlockText) return;
_textBlockText = value;
OnPropertyChanged(nameof(TextBlockText));
}
}
public List<string> AlternatingStrings { get; set; } = new List<string>();
public override void Run()
{
foreach (var s in AlternatingStrings)
{
TextBlockText = s;
if (dockPanel?.FirstTextBlock is TextBlock t)
GuiHelpers.GuiInvoke(() =>
{
t.Text = new string(s.Reverse().ToArray());
});
TapThread.Sleep(TimeSpan.FromSeconds(2));
Log.Info($"Set text to {s}");
}
}
}
public class MyDockPanel: ITapDockPanel
{
[Browsable(false)]
class dockResultListener : ResultListener
{
public Action RunStarted = null;
public override void OnTestPlanRunStart(TestPlanRun planRun)
{
RunStarted?.Invoke();
}
}
public TextBlock FirstTextBlock { get; set; }
public TextBlock SecondTextBlock { get; set; }
private TestPlan previousTestPlan = null;
void AddPlanHooks(TestPlan plan)
{
if (plan == previousTestPlan || plan == null) return;
previousTestPlan = plan;
var steps = plan.ChildTestSteps.RecursivelyGetAllTestSteps(TestStepSearch.EnabledOnly)
.OfType<MyTestStep>().ToArray();
void addStepHooks(MyTestStep step)
{
step.dockPanel = this;
step.PropertyChanged += (sender, args) =>
{
if (args.PropertyName == nameof(MyTestStep.TextBlockText))
GuiHelpers.GuiInvoke(() => SecondTextBlock.Text = step.TextBlockText);
};
}
foreach (var step in steps)
{
addStepHooks(step);
}
plan.ChildTestSteps.ChildStepsChanged += (list, action, step, index) =>
{
if (action == TestStepList.ChildStepsChangedAction.AddedStep && step is MyTestStep s)
addStepHooks(s);
};
}
public FrameworkElement CreateElement(ITapDockContext context)
{
var rl = new dockResultListener();
context.ResultListeners.Add(rl);
rl.RunStarted = () =>
{
GuiHelpers.GuiInvoke(() => AddPlanHooks(context.Plan));
};
AddPlanHooks(context.Plan);
var panel = new StackPanel() { Orientation = Orientation.Vertical };
FirstTextBlock = new TextBlock()
{
FontSize = 40,
HorizontalAlignment = HorizontalAlignment.Center,
Text = "Nothing here yet."
};
SecondTextBlock = new TextBlock()
{
FontSize = 40,
HorizontalAlignment = HorizontalAlignment.Center,
Text = "Nothing here yet."
};
panel.Children.Add(FirstTextBlock);
panel.Children.Add(SecondTextBlock);
return panel;
}
public double? DesiredWidth => 200;
public double? DesiredHeight => 200;
}
}