コンセプト
- 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 というシンプルな役割分担により、管理も拡張も容易です。