コンセプト
- XAML … UI の見た目を定義(カード・リスト・リンクなど)。
- PowerShell … JSON を読み込み、XAML にバインド、イベント処理(更新ボタン・リンククリックなど)。
- JSON … すべての表示データを記述。編集すれば即座に UI に反映。
1. JSON データ (cards.json)
{
"header": { "title": "ダッシュボード", "lastUpdated": "2025-10-03T06:00:00+09:00" },
"kpiCards": [
{ "title": "本日のジョブ", "value": 12, "unit": "件", "delta": "+2", "accent": "primary" },
{ "title": "エラー", "value": 1, "unit": "件", "delta": "-3", "accent": "alert" },
{ "title": "稼働率", "value": 98.5, "unit": "%", "delta": "+0.4", "accent": "ok" }
],
"progress": { "label": "全体進捗", "value": 35 },
"tasks": [
{ "title": "DBバックアップ", "state": "進行中", "due": "2025-10-05", "assignee": "ユーザーA" },
{ "title": "API キー更新", "state": "未着手", "due": "2025-10-07", "assignee": "チーム" }
],
"links": [
{ "label": "Redmine", "url": "https://example.com/redmine" },
{ "label": "API ドキュメント", "url": "https://example.com/docs" }
],
"news": [
{ "text": "新機能: レポートのエクスポートを追加" },
{ "text": "注意: API キーの更新期限が近づいています" }
]
}
2. PowerShell スクリプト (Main.ps1)
# ===== Main.ps1 =====
if ([Threading.Thread]::CurrentThread.ApartmentState -ne 'STA') {
$argsList = @('-sta','-NoProfile','-ExecutionPolicy','Bypass','-File', $PSCommandPath)
Start-Process -FilePath (Get-Command powershell).Source -ArgumentList $argsList | Out-Null
exit
}
Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase
Set-Location (Split-Path $PSCommandPath)
function Load-Xaml([string]$path) {
[xml]$xaml = Get-Content -LiteralPath $path -Raw
$reader = New-Object System.Xml.XmlNodeReader $xaml
[Windows.Markup.XamlReader]::Load($reader)
}
# JSON ロード関数
$Global:JsonPath = ".\\cards.json"
function Import-CardsJson {
Get-Content -LiteralPath $Global:JsonPath -Raw | ConvertFrom-Json
}
# XAML 読み込み
$window = Load-Xaml ".\\MainWindow.xaml"
# JSON を DataContext に
$data = Import-CardsJson
$window.DataContext = $data
# リンククリックイベントを追加
$window.AddHandler([System.Windows.Documents.Hyperlink]::RequestNavigateEvent,
[System.Windows.Navigation.RequestNavigateEventHandler]{
param($s,$e)
Start-Process $e.Uri.AbsoluteUri
$e.Handled = $true
})
# 更新ボタンの処理
$btnRefresh = $window.FindName("BtnRefresh")
if ($btnRefresh) {
$btnRefresh.Add_Click({
$fresh = Import-CardsJson
$window.DataContext = $fresh
[System.Windows.MessageBox]::Show("JSONを再読込しました。")
})
}
# ウィンドウ表示
$null = $window.ShowDialog()
3. XAML (MainWindow.xaml)
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding header.title, FallbackValue=ダッシュボード}"
Height="720" Width="1200" WindowStartupLocation="CenterScreen"
Background="White">
<Grid Margin="24">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="12"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="12"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="24"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Header -->
<DockPanel Grid.Row="0">
<StackPanel Orientation="Vertical" DockPanel.Dock="Left">
<TextBlock Text="{Binding header.title}" FontSize="28" FontWeight="Bold"/>
<TextBlock Margin="0,4,0,0" Foreground="Gray">
<Run Text="最終更新: "/>
<Run Text="{Binding header.lastUpdated}"/>
</TextBlock>
</StackPanel>
<Button x:Name="BtnRefresh" DockPanel.Dock="Right" Margin="8,0,0,0" Padding="12,6">更新</Button>
</DockPanel>
<!-- KPI Cards -->
<ItemsControl Grid.Row="2" ItemsSource="{Binding kpiCards}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><WrapPanel/></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="#DDD" BorderThickness="1" CornerRadius="8" Padding="12" Margin="6">
<StackPanel>
<TextBlock Text="{Binding title}" Foreground="Gray"/>
<StackPanel Orientation="Horizontal" Margin="0,6,0,0">
<TextBlock Text="{Binding value}" FontSize="24" FontWeight="Bold"/>
<TextBlock Text="{Binding unit}" Margin="6,6,0,0" Foreground="Gray"/>
</StackPanel>
<TextBlock Text="{Binding delta}" Foreground="Gray"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Progress -->
<Border Grid.Row="4" BorderBrush="#DDD" BorderThickness="1" CornerRadius="8" Padding="12">
<StackPanel>
<TextBlock Text="{Binding progress.label}" Foreground="Gray"/>
<ProgressBar Minimum="0" Maximum="100" Value="{Binding progress.value}" Height="12" Margin="0,12,0,0"/>
</StackPanel>
</Border>
<!-- Tasks + Links/News -->
<Grid Grid.Row="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="24"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Tasks -->
<Border Grid.Column="0" BorderBrush="#DDD" BorderThickness="1" CornerRadius="8" Padding="12">
<ItemsControl ItemsSource="{Binding tasks}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,8">
<TextBlock Text="{Binding title}" FontWeight="Bold"/>
<TextBlock Text="{Binding state}" Foreground="Gray"/>
<TextBlock Text="{Binding due}" Foreground="Gray"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<!-- Links + News -->
<StackPanel Grid.Column="2">
<Border BorderBrush="#DDD" BorderThickness="1" CornerRadius="8" Padding="12" Margin="0,0,0,12">
<ItemsControl ItemsSource="{Binding links}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Margin="0,0,0,6">
<Hyperlink NavigateUri="{Binding url}">
<Run Text="{Binding label}"/>
</Hyperlink>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<Border BorderBrush="#DDD" BorderThickness="1" CornerRadius="8" Padding="12">
<ItemsControl ItemsSource="{Binding news}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding text}" Margin="0,0,0,6"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</StackPanel>
</Grid>
</Grid>
</Window>
解説
仕組み
- DataContext に JSON オブジェクト全体を割り当てています。
- 各コントロールは Binding で JSON のプロパティを参照します。
- 例:
<TextBlock Text="{Binding header.title}"/>はcards.jsonのheader.titleを表示。
特徴
- JSON を編集するだけで UI が変わる
新しい KPI を追加したり、ニュースを差し替えたりできます。 - 更新ボタン で再読込 → DataContext を差し替え。
- Hyperlink のクリックは PowerShell 側で
Start-Processで処理。
応用
accent値を使って色を DataTrigger で切替可能。dueを日付形式にして並び替えや期限色分けも可能。
まとめ
これをベースに、業務向けのダッシュボードやタスク管理ビューに拡張できます。UI は XAML、データは JSON、制御は PowerShell というシンプルな役割分担により、管理も拡張も容易です。