This guide walks you through adding custom logic to displays using CodeBehind, enabling interactive behaviors, data manipulation, and dynamic responses to user actions. CodeBehind allows you to write .NET code (C# or VB.NET) that executes alongside your display.
Prerequisites:
CodeBehind is display-specific code that:
Every display CodeBehind includes these entry points:
csharp
public void DisplayOpening()
{
// Called when display is opening
// Initialize variables, setup handlers
}
public void DisplayIsOpen()
{
// Called periodically while display is open
// Update values, check conditions
}
public void DisplayClosing()
{
// Called when display is closing
// Cleanup, save state
}
For dialog displays:
csharp
public int DialogOnOK()
{
// Called when OK button pressed
// Return 1 to allow close
// Return 0 to prevent close
if (ValidateInput())
return 1;
else
return 0;
}
Access any display element by its Uid:
csharp
// Get reference to specific element
private Rectangle statusRect;
public void DisplayOpening()
{
// Access element by Uid
statusRect = this.CurrentDisplay.GetControl("22") as Rectangle;
// Modify properties
statusRect.Fill = Brushes.Green;
statusRect.Visibility = Visibility.Visible;
}
csharp
public void Button1_Click(object sender, InputEventArgs e)
{
// Your code here
@Tag.Motor1.Start = 1;
@Info.Trace("Motor started");
}
Handle multiple elements with one method:
csharp
public void AnyButton_Click(object sender, InputEventArgs e)
{
// Get the element that triggered event
var button = sender as Button;
// Use element properties
string buttonName = button.Name;
string uid = button.Uid;
// Take action based on which button
switch(uid)
{
case "StartBtn":
@Tag.Motor.Start = 1;
break;
case "StopBtn":
@Tag.Motor.Start = 0;
break;
}
}
csharp
private TSymbol mySymbol;
public void DisplayOpening()
{
// Get symbol by Uid
mySymbol = this.CurrentDisplay.GetControl("SymbolUID") as TSymbol;
// Access symbol properties
mySymbol.SetPropertyValue("State", 1);
// Note: #Source property not accessible via code
}
csharp
public void UpdateSymbol(string uid, int state)
{
TSymbol symbol = this.CurrentDisplay.GetControl(uid) as TSymbol;
if (symbol != null)
{
symbol.SetPropertyValue("State", state);
symbol.SetPropertyValue("Value", @Tag.Temperature);
}
}
csharp
private Ellipse movingElement;
public void DisplayOpening()
{
movingElement = this.CurrentDisplay.GetControl("MovingDot") as Ellipse;
}
public void MoveElement(double x, double y)
{
// Move element to new position
movingElement.Margin = new Thickness(x, y, 0, 0);
}
// Called from button click
public void AnimateMovement(object sender, InputEventArgs e)
{
double newX = @Tag.XPosition;
double newY = @Tag.YPosition;
MoveElement(newX, newY);
}
csharp
// Method 1: Using Display namespace (auto-updates if renamed)
@Display.AlarmScreen.Open();
// Method 2: Using Client namespace (manual string)
@Client.OpenDisplay("AlarmScreen");
// Method 3: Open as popup
@Display.MotorDetails.NewPopup();
// Method 4: With parameters
@Client.NewPopup("MotorDetails", "Motor1");
csharp
// Close current display
this.CurrentDisplay.Close();
// Close with dialog result
this.CurrentDisplay.DialogResult = true;
this.CurrentDisplay.Close();
Custom Properties are display-specific variables:
csharp
public void DisplayOpening()
{
// Set custom property
this.CurrentDisplay.SetCustomPropertyValue("LastUpdate", DateTime.Now);
this.CurrentDisplay.SetCustomPropertyValue("UserLevel", 2);
}
public void CheckProperty()
{
// Get custom property
object updateTime = this.CurrentDisplay.GetCustomPropertyValue("LastUpdate");
int level = Convert.ToInt32(
this.CurrentDisplay.GetCustomPropertyValue("UserLevel"));
}
// Get all as string (for debugging)
string allProps = this.CurrentDisplay.GetCustomPropertiesAsString();
csharp
public void DisplayIsOpen()
{
// Attach to mouse wheel event (only once)
if (!wheelAttached)
{
this.CurrentDisplay.GetThis().PreviewMouseWheel += PreviewMouseWheelChanged;
wheelAttached = true;
}
}
private bool wheelAttached = false;
private void PreviewMouseWheelChanged(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
// Zoom based on wheel direction
if (e.Delta > 0)
@Display.MainPage.ZoomLevel += 0.1;
else if (e.Delta < 0)
@Display.MainPage.ZoomLevel -= 0.1;
}
Problem: CodeBehind runs on UI thread, long operations freeze display.
Solution 1: Use async methods
csharp
public async void LongOperation()
{
await Task.Run(() =>
{
// Heavy processing here
});
}
Solution 2: Move to Scripts
? Keep methods short - Under 100ms execution ? Avoid loops in DisplayIsOpen() ? Cache element references in DisplayOpening() ? Use Scripts for heavy processing ? Minimize property access in loops
csharp
private bool motorRunning = false;
public void ToggleMotor(object sender, InputEventArgs e)
{
motorRunning = !motorRunning;
@Tag.Motor.Running = motorRunning ? 1 : 0;
Button btn = sender as Button;
btn.Content = motorRunning ? "STOP" : "START";
}
csharp
public int DialogOnOK()
{
TextBox input = this.CurrentDisplay.GetControl("InputBox") as TextBox;
if (string.IsNullOrEmpty(input.Text))
{
MessageBox.Show("Please enter a value");
return 0; // Prevent close
}
@Tag.UserInput = input.Text;
return 1; // Allow close
}
csharp
public void DisplayOpening()
{
// Access the main canvas
Canvas canvas = this.CurrentDisplay.GetControl("MainCanvas") as Canvas;
// Create new rectangle
Rectangle rect = new Rectangle();
rect.Width = 100;
rect.Height = 50;
rect.Fill = Brushes.Blue;
// Position and add to canvas
Canvas.SetLeft(rect, 100);
Canvas.SetTop(rect, 100);
canvas.Children.Add(rect);
}
Display freezes during CodeBehind execution
Cannot find element with GetControl
Changes don't appear
Symbol properties not updating
This guide covered adding custom logic to displays through CodeBehind, from basic event handling to advanced element manipulation, enabling rich interactive behaviors in your HMI application.