Windows Embedded Compact 7(WinCE7)環境下で Silverlight for Windows Embedded を用いた UI 開発を行う場合、ページ間の動的切り替えは標準的なナビゲーション機構を備えておらず、独自のコンポジション制御が必要となる。本稿では、XAML ベースのユーザーコントロールを動的にロード・置換するアプローチを、C++ 実装を中心に解説する。
基本設計思想は「ルートコンテナとして機能する Grid を保持し、その子要素コレクションに異なるページクラスのインスタンスを差し替える」ことにある。この方式により、アプリケーション全体の視覚的階層を一貫して管理しつつ、各ページのライフサイクルを明示的に制御可能となる。
1. ルートページの XAML 構造(MainPage.xaml)
以下は最小限のレイアウト構成であり、Gird_Layer_Source という名前の空の Grid を、ページ遷移の挿入ポイントとして定義している。
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="EmbeddedUI.MainPage"
Width="800" Height="480">
<Grid x:Name="LayoutRoot" Background="#000">
<Grid x:Name="Gird_Layer_Source" />
</Grid>
</UserControl>2. メインページの初期化(MainPage.cpp)
必要な名前付き要素(LayoutRoot および Gird_Layer_Source)を取得し、後続の動的描画処理に備える。
HRESULT MainPage::InitializeComponent()
{
HRESULT hr = E_FAIL;
FindName(L"LayoutRoot", &m_pLayoutRoot);
FindName(L"Gird_Layer_Source", &m_pGird_Layer_Source);
if (m_pLayoutRoot && m_pGird_Layer_Source)
{
hr = S_OK;
}
return hr;
}3. ページクラスの登録(App.cpp)
Silverlight for Windows Embedded では、すべてのカスタムコントロールが事前にアプリケーションに登録される必要がある。以下は MainPage と SecondPage の登録処理例である。
HRESULT App::RegisterUserControls()
{
static PFN_XRCUC_REGISTER s_pfnRegistrations[] =
{
&MainPage::Register,
&SecondPage::Register
};
HRESULT hr = S_OK;
for (size_t i = 0; i < _countof(s_pfnRegistrations) && SUCCEEDED(hr); ++i)
{
hr = s_pfnRegistrations[i]();
}
return hr;
}4. ページ遷移の制御ロジック(App.cpp)
アプリケーション起動時に、MainPage の子グリッド参照をグローバル変数 gpMainLayer に保持し、その後任意のタイミングで他のページを動的に追加・置換する。
// グローバル参照(ヘッダで宣言)
IXRGridPtr gpMainLayer = NULL;
// CreateHost 内で初期化
HRESULT App::CreateHost(XRWindowCreateParams* pCreateParams)
{
XRPtr<IXRCustomUserControl> pControl;
HRESULT hr = m_pApplication->CreateObject(__uuidof(MainPage), &pControl);
if (SUCCEEDED(hr))
{
hr = m_pApplication->CreateHostFromElementTree(pControl, pCreateParams, &m_pVisualHost);
// MainPage の子グリッドをキャプチャ
IXRCustomUserControl* pBase = static_cast<IXRCustomUserControl*>(pControl);
MainPage* pMain = dynamic_cast<MainPage*>(pBase);
if (pMain && pMain->m_pGird_Layer_Source)
{
gpMainLayer = pMain->m_pGird_Layer_Source;
}
}
return hr;
}
// OnStartup で遷移実行(例:起動直後に SecondPage を表示)
HRESULT App::OnStartup()
{
if (gpMainLayer)
{
IXRUIElementCollection* pChildren = nullptr;
gpMainLayer->GetChildren(&pChildren);
if (pChildren)
{
XRPtr<SecondPage> pTarget;
HRESULT hr = m_pApplication->CreateObject(__uuidof(SecondPage), &pTarget);
if (SUCCEEDED(hr) && pTarget)
{
pChildren->Clear(); // 既存コンテンツをクリア(オプション)
pChildren->Add(pTarget, nullptr);
}
pChildren->Release();
}
}
return S_OK;
}5. 遷移先ページの定義(SecondPage.xaml)
独立した XAML リソースとして定義され、Background やボタン配置など、独自のビジュアル構成を持つ。
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="EmbeddedUI.SecondPage"
Width="800" Height="480">
<Grid x:Name="LayoutRoot" Background="Green">
<Button Content="Second Page" Width="177" Height="38" Margin="65,54,0,0" />
<Button Content="Back to Main" Width="177" Height="38" Margin="65,117,0,0" />
</Grid>
</UserControl>