Repository navigation
workspace sdk pages
Pages provide UI content displayed in a monitor. Each page occupies one tab in a monitor and has its own lifecycle, from initialization through activation, deactivation, and disposal. Pages are typically opened by tasks but can also be created and added to monitors programmatically.
Use a page when your extension needs a full monitor tab with its own WPF view, lifecycle, and persisted state rather than a smaller UI component such as a widget, options page, or contextual action.
- The module creates a page instance and calls
Initialize(Workspace)to set up the page - If the client is connected and the page is not a
ConfigPageorReportPage,Initialize(Workspace)validates the SDK certificate, prepares the page, then calls the protectedInitialize()method where you assign theView - The page is added to a monitor's
PageCollectionthroughMonitor.Pages.Add(page) - When the page becomes the active tab, the framework calls
OnActivated(Monitor) - When the page loses focus to another tab, the framework calls
OnDeactivated(Monitor) - When the workspace saves, the framework calls
Serialize()to persist the page state - When the workspace restores, the framework calls
Deserialize(byte[])to restore the page state - When the page is closed, the framework calls
Dispose()if the page implementsIDisposable
Important
Standard Page subclasses require a valid SDK certificate when they initialize against a connected system. ConfigPage and ReportPage are exceptions with their own lifecycle rules.
Create a page by inheriting from Genetec.Sdk.Workspace.Pages.Page. Set the View property to a WPF UserControl that defines the page content:
public class MyPage : Genetec.Sdk.Workspace.Pages.Page
{
protected override void Initialize()
{
View = new MyPageView();
}
}Page implements INotifyPropertyChanged and extends DependencyObject, so it is the view model for its view. Bind your view's controls directly to page properties and call OnPropertyChanged() to raise change notifications:
public class MyPage : Genetec.Sdk.Workspace.Pages.Page
{
private string m_filter;
public string Filter
{
get => m_filter;
set { m_filter = value; OnPropertyChanged(nameof(Filter)); }
}
protected override void Initialize()
{
View = new MyPageView { DataContext = this };
}
}The SDK also provides TilePage, a Page subclass that adds tile layout management through its Pattern, States, and SynchronizeVideo properties. Use TilePage when the page itself needs a tile layout and tile-state collection.
| Member | Type | Description |
|---|---|---|
Id |
Guid | Unique page instance identifier. |
Type |
Guid | Page type identifier. Set automatically from the PageDescriptor when using PageAttribute. |
Name |
string | Display name shown on the page tab. Supports two-way data binding. |
View |
UIElement | The WPF content displayed when the page is active. Assign this in Initialize(). |
IsActive |
bool (readonly) | Whether the page is currently the active tab on its monitor. |
IsClosed |
bool (readonly) | Whether the page has been closed. |
Workspace |
Workspace | The workspace instance. Available after Initialize(Workspace) is called. |
| Method | Description |
|---|---|
Initialize() |
Protected virtual. Override to set up the page and assign View. Called by the framework during Initialize(Workspace). |
OnActivated(Monitor) |
Protected virtual. Called when the operator switches to this page's tab on a monitor. Also called when the page is first set as the active page. |
OnDeactivated(Monitor) |
Protected virtual. Called when the operator switches away from this page's tab to another page on the same monitor. |
To clean up resources when the page is closed, implement IDisposable on your page class. The framework checks for IDisposable and calls Dispose() when the page is removed.
public class MyPage : Genetec.Sdk.Workspace.Pages.Page, IDisposable
{
protected override void Initialize()
{
View = new MyPageView();
}
protected override void OnActivated(Monitor monitor)
{
// Page became the active tab
}
protected override void OnDeactivated(Monitor monitor)
{
// Page is no longer the active tab
}
public void Dispose()
{
// Clean up event subscriptions
// and other resources
}
}Operators can save the current workspace as a private or public configuration. Private configurations are stored per user in the Directory database. Public configurations are stored as shared entities accessible based on partition permissions.
When an operator saves a workspace, the framework calls Serialize() on each open page to capture its data. When the operator later loads that saved workspace, the framework recreates each page and calls Deserialize(byte[]) to restore it. Deserialize is only called when restoring from a saved workspace. It is not called when a page is opened for the first time.
Page-specific data includes anything the page needs to return to the same view the operator left: filter criteria, selected entities, sort order, text input, or display settings.
Override Serialize to return the page data as a byte array, and Deserialize to restore it. The serialization format is up to you. This example uses JSON:
public class SerializablePage : Genetec.Sdk.Workspace.Pages.Page
{
private string m_filter;
private Guid m_selectedEntityId;
protected override void Initialize()
{
View = new MyPageView { DataContext = this };
}
protected override byte[] Serialize()
{
var state = new
{
Filter = m_filter,
SelectedEntityId = m_selectedEntityId
};
string json = JsonSerializer.Serialize(state);
return Encoding.UTF8.GetBytes(json);
}
protected override void Deserialize(byte[] data)
{
if (data == null)
return;
string json = Encoding.UTF8.GetString(data);
var state = JsonSerializer.Deserialize<JsonElement>(json);
m_filter = state.GetProperty("Filter").GetString();
m_selectedEntityId = state.GetProperty("SelectedEntityId").GetGuid();
}
}Override CanSave() to control whether the page is included when saving the workspace. Returns true by default.
A PageDescriptor provides metadata about a page type. The descriptor defines the name, icon, thumbnail, and category that appear on the home page without instantiating the page itself.
| Member | Type | Description |
|---|---|---|
Name |
string (abstract) | Default page name displayed on the home page and tab header. |
Type |
Guid (abstract) | Unique page type identifier. |
Description |
string (virtual) | Page description. Defaults to empty. |
CategoryId |
Guid (virtual) | Task category for home page placement. Use a TaskCategories constant. Defaults to Guid.Empty. |
Icon |
ImageSource (virtual) | 16x16 icon shown in the tab header. The SDK provides a default if not set. |
Thumbnail |
ImageSource (virtual) | 256x256 image shown on the home page tile. The SDK provides a default if not set. |
PositionIndex |
int (virtual) | Sort priority on the home page (default 0). |
AllowOfflineExecution |
bool (virtual) | Whether the page is visible when disconnected from the server. Defaults to true. |
IconColor |
TaskIconColor (virtual) | Icon color displayed on the home page. |
The TaskCategories class provides constants for the built-in home page groups:
| Constant | Description |
|---|---|
TaskCategories.Operation |
Operational monitoring tasks. |
TaskCategories.Investigation |
Investigation and report tasks. |
TaskCategories.Maintenance |
System maintenance tasks. |
TaskCategories.Administration |
Administrative tasks. |
TaskCategories.Diagnosis |
Diagnostic tasks. |
public override Guid CategoryId => new Guid(TaskCategories.Investigation);| Method | Description |
|---|---|
HasPrivilege() |
Return true if the current user has permission to access this page type. Defaults to true. Override to restrict access based on user privileges. |
Initialize(IEngine) |
Called by the framework during task initialization, before HasPrivilege() is ever called. After this call, the protected m_sdk field is available for privilege checks. |
Override HasPrivilege() to hide the task from the home page when the current user lacks a required privilege. The m_sdk field is available because the framework calls Initialize(IEngine) before HasPrivilege():
public class MyPageDescriptor : PageDescriptor
{
private static readonly Guid MyPrivilegeId = new Guid("11111111-1111-1111-1111-111111111111");
public override string Name => "My Custom Page";
public override Guid Type => new Guid("22222222-2222-2222-2222-222222222222");
public override bool HasPrivilege()
{
return m_sdk.SecurityManager.IsPrivilegeGranted(MyPrivilegeId);
}
}When HasPrivilege() returns false, the CreatePageTask<T> reports that it cannot execute, and the home page hides the task.
Apply PageAttribute to your page class, passing the descriptor type. The descriptor must derive from PageDescriptor and have a public constructor with no parameters. The page view is a standard WPF UserControl.
<UserControl
x:Class="MyModule.MyPageView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="10">
<TextBox x:Name="FilterTextBox" />
<ListBox x:Name="EntityList" />
</StackPanel>
</UserControl>[Page(typeof(MyPageDescriptor))]
public class MyPage : Genetec.Sdk.Workspace.Pages.Page
{
protected override void Initialize()
{
View = new MyPageView();
}
}
public class MyPageDescriptor : PageDescriptor
{
public override string Name => "My Custom Page";
public override Guid Type => new Guid("22222222-2222-2222-2222-222222222222");
public override Guid CategoryId => new Guid(TaskCategories.Operation);
public override ImageSource Thumbnail => new BitmapImage(new Uri(@"pack://application:,,,/MY-ASSEMBLY;Component/Resources/MY-THUMBNAIL.png", UriKind.RelativeOrAbsolute));
}CreatePageTask<T> reads the PageAttribute to extract the descriptor and use its metadata for the task's name, icon, thumbnail, category, and privilege check.
CreatePageTask<T> is a generic task that creates and opens a page of type T. This simplifies the common pattern of creating a task that opens a page:
public class SampleModule : Module
{
private CreatePageTask<MyPage> m_task;
public override void Load()
{
m_task = new CreatePageTask<MyPage>();
m_task.Initialize(Workspace);
Workspace.Tasks.Register(m_task);
}
public override void Unload()
{
if (m_task != null)
{
Workspace.Tasks.Unregister(m_task);
m_task = null;
}
}
}The page class must be public, have a public constructor with no parameters, and have a PageAttribute with a valid descriptor.
By default, executing a CreatePageTask<T> creates a new page instance each time. To allow only one instance:
public CreatePageTask<MyPage> CreateSingletonTask()
{
return new CreatePageTask<MyPage>(isSingleton: true);
}When isSingleton is true, executing the task activates the existing page instead of creating a new one. If the page exists on a different monitor, it is moved to the active monitor.
When executed, CreatePageTask<T>:
- For singleton pages, searches all monitors for an existing instance of type
T - If no existing page is found, creates a new instance using the parameterless constructor and calls
Initialize(Workspace) - Adds the page to the active monitor's page collection
- Sets the page as the active page on the monitor
Each Monitor has a PageCollection accessible through Monitor.Pages:
| Member | Description |
|---|---|
Add(Page) |
Add a page to the monitor. |
Remove(Page) |
Remove a page from the monitor. |
Contains(Page) |
Check if a specific page instance exists. |
Contains(PageDescriptor) |
Check for a page whose PageAttribute descriptor has the same Type GUID as the supplied descriptor. Pages without PageAttribute are not matched. |
Count |
The number of pages on the monitor. |
this[int] |
Get a page by index. |
Set Monitor.ActivePage to switch the active tab:
public void OpenPageOnActiveMonitor(Workspace workspace)
{
var page = new MyPage();
page.Initialize(workspace);
workspace.ActiveMonitor.Pages.Add(page);
workspace.ActiveMonitor.ActivePage = page;
}- About the Workspace SDK: Workspace SDK architecture and module lifecycle.
- About workspace modules: Workspace module class and Load/Unload lifecycle.
- About tasks: Adding executable menu items and home tasks.
- About custom report pages: Custom report pages embedded in tasks.
- About Workspace SDK certificates: Certificate requirements for workspace components.
- About workspace services: Built-in workspace services and how to consume them.
- Overview
- Connecting to Security Center
- SDK certificates
- Referencing SDK assemblies
- ASP.NET hosting
- SDK compatibility
- Migrating to modern .NET
- Entities
- Entity cache
- Entity loading, cache, and query options
- Detecting entity changes
- Entity change event reference
- Transactions
- Security Center events
- Actions
- Security Desk
- Custom events
- Event-to-actions
- Managing macros
- ReportManager
- ReportManager query reference
- Access control raw events
- DownloadAllRelatedData and StrictResults
- Privileges
- Partitions
- Entity write restrictions
- About custom fields
- About video
- About cameras
- Enrolling a video unit
- Ingesting third-party video
- Archiver and auxiliary archiver roles
- Archive transfer
- About access control
- About cardholders and credentials
- About doors, areas, elevators, and access points
- About access rules and schedules
- About access control units and interface modules
- Enrolling an access control unit
- Door templates
- Visitors
- Mobile credentials
- About threat levels
- About alarms
- About incidents
- Maps
- Logging
- Overview
- Localization
- Certificates
- Lifecycle
- Threading
- State management
- Configuration
- Restricted configuration
- Events
- Queries
- Request manager
- Database
- Entity ownership
- Engine extensions
- Entity mappings
- Server management
- Custom privileges
- Custom entity types
- Resolving non-SDK assemblies
- Deploying plugins
- Modern .NET support
- Overview
- Localization
- Certificates
- Creating modules
- Tasks
- Pages
- Components
- Tile extensions
- Services
- Contextual actions
- Custom actions
- Options extensions
- Configuration pages
- Monitors
- Shared components
- Commands
- Extending events
- Map extensions
- Timeline providers
- Image extractors
- Credential encoders
- Credential readers
- Cardholder fields extractors
- Badge printers
- Content builders
- Dashboard widgets
- Incidents
- Logon providers
- Pinnable content builders
- Custom report pages
- Overview
- Getting started
- Media file formats
- MediaPlayer
- VideoSourceFilter
- MediaExporter
- MediaFile
- G64 converters
- FileCryptingManager
- PlaybackSequenceQuerier
- PlaybackStreamReader
- OverlayFactory
- PtzCoordinatesManager
- AudioTransmitter
- AudioRecorder
- AnalogMonitorController
- Camera blocking
- Overview
- Getting started
- Referencing entities
- Entity operations
- About access control in the Web SDK
- About video in the Web SDK
- Users and user groups
- Partitions
- Custom fields
- Custom card formats
- Actions
- Events and alarms
- Incidents
- Reports
- Tasks
- Macros
- Custom entity types
- System endpoints
- Performance guide
- Reference
- Endpoints
- Constants
- Enumerations
- Under the hood
- Troubleshooting