一键导入
dotnet-wpf-comparison-view
こんなときに使う: WPFでサイドバイサイド比較ビューを構築。不一致ハイライトとチェックボックス検証付きのマッチング結果表示。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
こんなときに使う: WPFでサイドバイサイド比較ビューを構築。不一致ハイライトとチェックボックス検証付きのマッチング結果表示。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
モダン C#(12+)で record、パターンマッチング、合成、Result 型エラーハンドリングを使った 慣用的で高性能なコードを書く。こんなときに使う: 新規 C# コードの作成、API 設計、 または C# 12+ イディオムへのリファクタリング。
こんなときに使う: WPFアプリケーションに社員番号入力ダイアログを追加し、 DPAPIで暗号化された設定として社員IDを安全に保存したいとき。
こんなときに使う: 繰り返し発生する業務問い合わせ(監査、アンケート、コンプライアンス調査)に対して、 過去の回答実績とエビデンスを活用して回答するためのテンプレートスキル。 再利用可能な7ステップワークフローとスキャフォールディングファイルを提供する。
こんなときに使う: PDFテキスト抽出、Optical Character Recognition (OCR)、結合/分割、フォーム処理をuvベースの再現可能コマンドで実行したいときに使う。
こんなときに使う: Migrate Access SQL to Oracle, generate .NET C# code. Use when converting Access queries to Oracle.
こんなときに使う: .NETドメイン層で汎用的な重み付きフィールドマッチングとスコアリングを実装。
| name | dotnet-wpf-comparison-view |
| description | こんなときに使う: WPFでサイドバイサイド比較ビューを構築。不一致ハイライトとチェックボックス検証付きのマッチング結果表示。 |
マッチング結果をサイドバイサイドで表示する比較ビュー構築のエンドツーエンドワークフロー:スコア追跡付き比較項目ViewModel、3カラムXAMLレイアウト(フィールド名 / ソースA / ソースB)、背景色による不一致ハイライト、ライブスコア再計算付き編集可能フィールド、エクスポート前のチェックボックスベースのユーザー検証。
以下の場合にこのスキルを使用してください:
前提条件:
CommunityToolkit.Mvvmがインストール済みのWPFアプリケーションdotnet-generic-matching)dotnet-generic-matching — このビューで表示するマッチング結果を提供dotnet-wpf-pdf-preview — 比較ビューと並べて表示するPDFプレビューパネルdotnet-oracle-wpf-integration — OracleからソースA候補データを読み込みdotnet-wpf-dify-api-integration — AI OCR経由でソースBデータを抽出git-commit-practices — 各ステップをアトミックな変更としてコミットCommunityToolkit.Mvvm(ObservableObject、[ObservableProperty]、[RelayCommand])dotnet-generic-matching)x:Nameでのコントロール操作は禁止(基礎と型)スコア、ソースフィールド、背景色、チェックボックスを持つ単一の比較行を表すViewModelを定義するときに使用します。
ObservableObjectを継承したComparisonItemViewModelを作成します。各インスタンスは1つのマッチングペアを保持:ソースAフィールド(例:データベースレコード)、ソースBフィールド(例:OCR抽出データ)、不一致ハイライト用の背景色、ユーザー検証用のチェックボックスプロパティ。
YourApp/
├── ViewModels/
│ ├── ComparisonItemViewModel.cs # 🆕 Single comparison row
│ └── ComparisonTabViewModel.cs # 🆕 Parent with ObservableCollection
└── Views/
└── ComparisonView.xaml # 🆕 3-column layout
ComparisonItemViewModel.cs — コア構造:
using CommunityToolkit.Mvvm.ComponentModel;
namespace YourApp.ViewModels
{
public partial class ComparisonItemViewModel : ObservableObject
{
// === Score ===
[ObservableProperty] private int index;
[ObservableProperty] private double scorePercent;
[ObservableProperty] private bool isSuccessful;
[ObservableProperty] private string scoreColor = "Black";
// === Source A fields (read-only, e.g., database record) ===
[ObservableProperty] private string sourceAField1 = "";
[ObservableProperty] private string sourceAField2 = "";
[ObservableProperty] private string sourceAField3 = "";
// === Source B fields (e.g., OCR-extracted data) ===
[ObservableProperty] private string sourceBField1 = "";
[ObservableProperty] private string sourceBField2 = "";
[ObservableProperty] private string sourceBField3 = "";
// === Background colors for mismatch highlighting ===
[ObservableProperty] private string sourceBField1Background = "Transparent";
[ObservableProperty] private string sourceBField2Background = "Transparent";
[ObservableProperty] private string sourceBField3Background = "Transparent";
// === Checkbox verification per field ===
[ObservableProperty] private bool isField1Checked;
[ObservableProperty] private bool isField2Checked;
[ObservableProperty] private bool isField3Checked;
// === Editable fields (trigger recalculation) ===
[ObservableProperty] private decimal editableUnitPrice;
[ObservableProperty] private string editableDeliveryDate = "";
[ObservableProperty] private bool isModified = false;
// === Editable field backgrounds ===
[ObservableProperty] private string editableUnitPriceBackground = "White";
partial void OnEditableUnitPriceChanged(decimal value)
{
IsModified = true;
UpdateMismatchBackgrounds();
RecalculateMatchingScore();
}
partial void OnIsField1CheckedChanged(bool value)
{
UpdateMismatchBackgrounds();
}
/// <summary>
/// Update backgrounds: pink (#F8D7DA) for mismatch, green (#BBF7D0) when checked, Transparent otherwise.
/// </summary>
public void UpdateMismatchBackgrounds()
{
SourceBField1Background = IsField1Checked ? "#BBF7D0"
: IsMismatch(SourceAField1, SourceBField1) ? "#F8D7DA"
: "Transparent";
SourceBField2Background = IsField2Checked ? "#BBF7D0"
: IsMismatch(SourceAField2, SourceBField2) ? "#F8D7DA"
: "Transparent";
SourceBField3Background = IsField3Checked ? "#BBF7D0"
: IsMismatch(SourceAField3, SourceBField3) ? "#F8D7DA"
: "Transparent";
}
private static bool IsMismatch(string? a, string? b)
=> (a ?? string.Empty) != (b ?? string.Empty);
/// <summary>
/// Count visible fields that have not been checked by the user.
/// </summary>
public int GetUncheckedVisibleCount()
{
int count = 0;
if (HasDisplayValue(SourceAField1) && !IsField1Checked) count++;
if (HasDisplayValue(SourceAField2) && !IsField2Checked) count++;
if (HasDisplayValue(SourceAField3) && !IsField3Checked) count++;
return count;
}
/// <summary>
/// Recalculate matching score after editable field changes.
/// Delegate to domain matching service with updated values.
/// </summary>
private void RecalculateMatchingScore()
{
// Re-run matching with updated values via domain service
// ScorePercent = newResult.Score.ScorePercent;
// IsSuccessful = ScorePercent >= 80.0;
// ScoreColor = IsSuccessful ? "Green" : "Red";
}
public void UpdateScoreColor()
{
ScoreColor = IsSuccessful ? "Green" : (ScorePercent >= 60 ? "Orange" : "Red");
}
// === Visibility (HasDisplayValue pattern) ===
public bool IsField1Visible => HasDisplayValue(SourceAField1);
public bool IsField2Visible => HasDisplayValue(SourceAField2);
public bool IsField3Visible => HasDisplayValue(SourceAField3);
private static bool HasDisplayValue(string? value)
{
if (string.IsNullOrWhiteSpace(value)) return false;
return value.Trim() != "-";
}
partial void OnSourceAField1Changed(string value)
{
OnPropertyChanged(nameof(IsField1Visible));
}
}
}
MercuryのMatchingResultItemViewModelからの主要パターン:
partial void OnXxxChanged()フックによる変更追跡と再計算HasDisplayValue()で空値/ダッシュ値を表示から除外"Transparent"、"#F8D7DA"、"#BBF7D0")GetUncheckedVisibleCount()でエクスポート前にすべての表示フィールドがチェック済みか検証Values: 基礎と型 / 成長の複利
フィールド名、ソースA、ソースBの列を持つItemsControlベースの比較ビューを作成するときに使用します。
スクロール可能なItemsControlと、3カラムGridを含むDataTemplateを作成します。各マッチング結果はスコアヘッダーとフィールド行を持つボーダー付きカードとして描画されます。
ComparisonView.xaml — レイアウトテンプレート:
<UserControl x:Class="YourApp.Views.ComparisonView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<Style x:Key="FieldNameStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="11"/>
<Setter Property="Padding" Value="5,2"/>
<Setter Property="Background" Value="#F5F5F5"/>
</Style>
<Style x:Key="ValueStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="11"/>
<Setter Property="Padding" Value="5,2"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</UserControl.Resources>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" FontSize="16" FontWeight="Bold"
Text="Comparison Results" Margin="0,0,0,10"/>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding ComparisonItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="#CCCCCC" BorderThickness="1"
Margin="0,0,0,15" Padding="10"
Background="#FAFAFA" CornerRadius="5">
<StackPanel>
<!-- Score Header -->
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" FontSize="14" FontWeight="Bold"
Text="{Binding Index, StringFormat='#{0}'}"/>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<TextBlock Text="Score: " FontSize="12"/>
<TextBlock Text="{Binding ScorePercent, StringFormat={}{0:F1}%}"
FontSize="12" FontWeight="Bold"
Foreground="{Binding ScoreColor}"/>
</StackPanel>
</Grid>
<Separator Margin="0,0,0,10"/>
<!-- 3-Column Comparison Grid -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140"/> <!-- Field Name -->
<ColumnDefinition Width="*"/> <!-- Source A -->
<ColumnDefinition Width="*"/> <!-- Source B -->
</Grid.ColumnDefinitions>
<!-- Column Headers -->
<TextBlock Grid.Column="0" Grid.Row="0"
Text="Field" FontWeight="Bold" FontSize="11"/>
<TextBlock Grid.Column="1" Grid.Row="0"
Text="Source A" FontWeight="Bold" FontSize="11"/>
<TextBlock Grid.Column="2" Grid.Row="0"
Text="Source B" FontWeight="Bold" FontSize="11"/>
<!-- Field Row Example -->
<TextBlock Grid.Column="0" Grid.Row="1"
Text="Field 1" Style="{StaticResource FieldNameStyle}"/>
<TextBlock Grid.Column="1" Grid.Row="1"
Text="{Binding SourceAField1}"
Style="{StaticResource ValueStyle}"/>
<TextBlock Grid.Column="2" Grid.Row="1"
Text="{Binding SourceBField1}"
Background="{Binding SourceBField1Background}"
Style="{StaticResource ValueStyle}"/>
<!-- Add Grid.RowDefinitions and more rows per field... -->
</Grid>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
DataGridではなくItemsControlを使う理由:DataGridは選択、ソート、編集用のUIクロムを追加し、カスタム比較レイアウトと競合します。ItemsControlはアイテムごとのDataTemplateを完全に制御できます。
Values: 基礎と型 / ニュートラル
閾値に基づいてスコア値に色分けスタイルを適用するときに使用します。
スコア色ロジックをViewModel内に実装します(IValueConverterとしてではなく)。これによりテスト容易性が向上します。ViewModelはScoreColor文字列プロパティを公開し、XAMLがForegroundにバインドします。
// In ComparisonItemViewModel
public void UpdateScoreColor()
{
// ✅ Green ≥80%, Orange 60–79%, Red <60%
ScoreColor = IsSuccessful ? "Green" : (ScorePercent >= 60 ? "Orange" : "Red");
}
<!-- ✅ CORRECT — Bind to ViewModel color property -->
<TextBlock Text="{Binding ScorePercent, StringFormat={}{0:F1}%}"
Foreground="{Binding ScoreColor}" FontWeight="Bold"/>
<!-- ❌ WRONG — IValueConverter for simple threshold logic -->
<TextBlock Foreground="{Binding ScorePercent, Converter={StaticResource ScoreColorConverter}}"/>
IValueConverterではなくViewModelプロパティを使う理由:3段階の閾値ロジック(Green/Orange/Red)はドメイン的に意味があります。ViewModelに配置することで、XAMLインフラなしでテスト可能になります。
Values: 基礎と型 / ニュートラル
ユーザーが変更可能なTextBoxバインディングを追加し、黄色背景とライブ再計算を実現するときに使用します。
即座のフィードバックのためにTwoWayバインディングとUpdateSourceTrigger=PropertyChangedを使用します。編集可能フィールドは読み取り専用フィールドと視覚的に区別するため、独自の背景色(黄色#FFFFCCまたは白)を持ちます。
<!-- ✅ Editable field with TwoWay binding and yellow background -->
<TextBox Grid.Column="2" Grid.Row="5"
Text="{Binding EditableUnitPrice, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
StringFormat={}{0:N0}}"
Background="{Binding EditableUnitPriceBackground}"
FontSize="11" Padding="3,1"/>
<!-- ✅ Read-only field (TextBlock, not TextBox) -->
<TextBlock Grid.Column="2" Grid.Row="1"
Text="{Binding SourceBField1}"
Background="{Binding SourceBField1Background}"
Style="{StaticResource ValueStyle}"/>
ViewModelの変更ハンドラー — 編集時に再計算をトリガー:
partial void OnEditableUnitPriceChanged(decimal value)
{
IsModified = true;
UpdateMismatchBackgrounds();
RecalculateMatchingScore();
}
主要ポイント:
decimalを使用(floatやdoubleは使用禁止)UpdateSourceTrigger=PropertyChangedはキーストロークごとに発火しライブ更新を実現IsModifiedフラグで編集可能フィールドの変更を追跡Values: 継続は力 / 基礎と型
ユーザーがフィールドを確認したことを示すために、フィールドごとのチェックボックスを追加するときに使用します。
手動検証が必要なフィールドにCheckBox列(またはインラインCheckBox)を追加します。チェック時に背景がグリーン(#BBF7D0)に変わります。GetUncheckedVisibleCount()メソッドで、エクスポート前にすべての表示フィールドがチェック済みか検証します。
<!-- Checkbox column (between Source A and Source B, or after Source B) -->
<CheckBox Grid.Column="3" Grid.Row="1"
IsChecked="{Binding IsField1Checked}"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
ViewModel — チェックボックスが背景更新をトリガー:
partial void OnIsField1CheckedChanged(bool value)
{
UpdateMismatchBackgrounds();
}
public void UpdateMismatchBackgrounds()
{
// Green when checked, pink when mismatched, transparent when matching
SourceBField1Background = IsField1Checked ? "#BBF7D0"
: IsMismatch(SourceAField1, SourceBField1) ? "#F8D7DA"
: "Transparent";
}
色の凡例:
| 色 | 16進コード | 意味 |
|---|---|---|
| 🆕 ピンク | #F8D7DA | ソースAとソースBの間で不一致を検出 |
| ✅ グリーン | #BBF7D0 | ユーザーがフィールドを検証・チェック済み |
| 透明 | Transparent | フィールドが一致(対応不要) |
Values: ニュートラル / 基礎と型
比較ビューを親ViewModelに接続し、結果を展開し、エクスポートゲートを実装するときに使用します。
ObservableCollection<ComparisonItemViewModel>とSetResultsメソッドを持つ親ComparisonTabViewModelを作成します。各アイテムのPropertyChangedをサブスクライブしてライブプレビュー更新を実現します。全チェック済み+全スコア閾値超過でエクスポートをゲートします。
ComparisonTabViewModel.cs:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
namespace YourApp.ViewModels
{
public partial class ComparisonTabViewModel : ObservableObject
{
public ObservableCollection<ComparisonItemViewModel> ComparisonItems { get; } = new();
[ObservableProperty]
private string qualityMessage = string.Empty;
public event EventHandler<string>? ExportCompleted;
/// <summary>
/// Populate from matching results with PropertyChanged subscription.
/// </summary>
public void SetResults(IEnumerable<MatchingResultData> results)
{
ComparisonItems.Clear();
int idx = 1;
foreach (var result in results)
{
var item = new ComparisonItemViewModel
{
Index = idx++,
ScorePercent = result.ScorePercent,
IsSuccessful = result.ScorePercent >= 80.0,
SourceAField1 = result.SourceAField1,
SourceBField1 = result.SourceBField1,
// ... map remaining fields
};
item.UpdateScoreColor();
item.UpdateMismatchBackgrounds();
// ✅ Subscribe for live preview updates
item.PropertyChanged += (s, e) => UpdateExportPreview();
ComparisonItems.Add(item);
}
UpdateExportPreview();
}
private void UpdateExportPreview()
{
int total = ComparisonItems.Count;
int qualified = ComparisonItems.Count(i => i.IsSuccessful);
QualityMessage = qualified == total
? $"✅ All scores ≥80% ({qualified}/{total}). Export ready."
: $"⚠ {qualified}/{total} items ≥80%. All must pass before export.";
}
[RelayCommand]
private void Export()
{
// Gate 1: All checkboxes must be checked
var unchecked = ComparisonItems.Sum(i => i.GetUncheckedVisibleCount());
if (unchecked > 0)
{
ExportCompleted?.Invoke(this,
$"❌ {unchecked} unchecked items remain. Check all before export.");
return;
}
// Gate 2: All scores must be ≥ threshold
int total = ComparisonItems.Count;
int qualified = ComparisonItems.Count(i => i.IsSuccessful);
if (qualified < total)
{
ExportCompleted?.Invoke(this,
$"❌ {qualified}/{total} items ≥80%. All must pass.");
return;
}
// Execute export
// var outputPath = _exportUseCase.Execute(results);
ExportCompleted?.Invoke(this, $"✅ Exported {total} items.");
}
}
}
2つのエクスポートゲートを設ける理由:ゲート1(チェックボックス)はユーザーがすべてのフィールドを目視確認したことを保証します。ゲート2(スコア閾値)はデータ品質を保証します。両方を通過する必要があります — これはMercuryのResultTabViewModel.ExportRpaDataパターンに倣っています。
Values: 基礎と型 / 継続は力
✅ 不一致フィールドに#F8D7DA(ピンク)、検証済みフィールドに#BBF7D0(グリーン)、一致フィールドにTransparentを適用します。背景をViewModelの文字列プロパティにバインドします。
// ✅ CORRECT — ViewModel drives background color via binding
SourceBField1Background = IsField1Checked ? "#BBF7D0"
: IsMismatch(SourceAField1, SourceBField1) ? "#F8D7DA"
: "Transparent";
Values: ニュートラル(即座の視覚フィードバック)
✅ partial void OnXxxChanged()フックを使用して、ユーザーがフィールドを編集した際に即座にRecalculateMatchingScore()をトリガーします。これにより、編集がマッチングを改善したかどうかの即座のフィードバックが得られます。
partial void OnEditableUnitPriceChanged(decimal value)
{
IsModified = true;
UpdateMismatchBackgrounds();
RecalculateMatchingScore();
}
Values: 継続は力(リアルタイム再計算)
✅ GetUncheckedVisibleCount()を使用して、すべての表示フィールドが確認済みであることを保証します。HasDisplayValueがtrueを返すフィールドのみカウントし、空値やプレースホルダー値はスキップします。
var unchecked = ComparisonItems.Sum(i => i.GetUncheckedVisibleCount());
if (unchecked > 0) { /* Block export */ }
Values: 基礎と型(品質ゲート)
問題:ユーザーがフィールドを編集したりチェックボックスをチェックしても、エクスポートプレビューが更新されない。親ViewModelが子アイテムの変更をリッスンしていないことが原因。
解決策:SetResults()内で各ComparisonItemViewModel.PropertyChangedをサブスクライブします。
// ❌ WRONG — No subscription, preview is stale
ComparisonItems.Add(item);
// ✅ CORRECT — Subscribe for live updates
item.PropertyChanged += (s, e) => UpdateExportPreview();
ComparisonItems.Add(item);
問題:XAMLで静的な値で背景色を直接設定。データ変更時に不一致ハイライトが更新されない。
解決策:BackgroundをUpdateMismatchBackgrounds()が動的に更新するViewModelの文字列プロパティにバインドします。
<!-- ❌ WRONG — Static background, never updates -->
<TextBlock Background="#F8D7DA" Text="{Binding SourceBField1}"/>
<!-- ✅ CORRECT — Dynamic background via binding -->
<TextBlock Background="{Binding SourceBField1Background}" Text="{Binding SourceBField1}"/>
問題:ユーザーが新しいデータセットを読み込んだ際に以前のマッチング結果が残り、古いデータで混乱を招く。
解決策:SetResults()の先頭でComparisonItems.Clear()を呼び出し、すべての品質メッセージをリセットします。
public void SetResults(IEnumerable<MatchingResultData> results)
{
// ✅ Always clear previous state first
ComparisonItems.Clear();
QualityMessage = string.Empty;
// ... populate new results
}
What:データバインディングの代わりにx:Nameを使用してcode-behindからTextBlockの色や背景を直接設定。
Why It's Wrong:MVVM違反。ViewModelがUIコントロールに依存するとユニットテストができません。背景色ロジックがテストから見えなくなります。
Better Approach:ViewModelで色を文字列プロパティとして公開。XAMLでBackground="{Binding FieldBackground}"にバインド。ViewModelプロパティを直接テスト。
// ❌ WRONG — Direct UI manipulation
Field1TextBlock.Background = new SolidColorBrush(Colors.Pink);
// ✅ CORRECT — ViewModel property with binding
[ObservableProperty] private string sourceBField1Background = "Transparent";
What:XAMLトリガー、code-behind、またはバリューコンバーターで不一致ステータスやスコアを計算。
Why It's Wrong:比較ロジックはアプリケーション/ドメインロジックです。View層に配置するとテスト不能になり、ビジネスルールがUIフレームワークに結合されます。
Better Approach:IsMismatch()、UpdateMismatchBackgrounds()、RecalculateMatchingScore()をViewModelに配置。Viewは結果のプロパティにバインドするのみ。
// ❌ WRONG — Mismatch check in IValueConverter
public object Convert(object[] values, ...) =>
values[0]?.ToString() != values[1]?.ToString() ? Brushes.Pink : Brushes.Transparent;
// ✅ CORRECT — Mismatch check in ViewModel
private static bool IsMismatch(string? a, string? b)
=> (a ?? string.Empty) != (b ?? string.Empty);
ComparisonItemViewModelを作成(Step 1)UpdateMismatchBackgrounds()を追加(Step 1)GetUncheckedVisibleCount()を追加(Step 1)HasDisplayValue可視性パターンを追加(Step 1)ItemsControlとDataTemplateによる3カラムXAMLレイアウトを構築(Step 2)FieldNameStyleとValueStyleリソーススタイルを追加(Step 2)UpdateScoreColor()を実装(Step 3)TwoWay + UpdateSourceTrigger=PropertyChangedの編集可能TextBoxフィールドを追加(Step 4)partial void OnXxxChanged()をRecalculateMatchingScore()に接続(Step 4)IsFieldXCheckedにバインドしたCheckBoxを追加(Step 5)ObservableCollectionとSetResults()を持つ親ViewModelを作成(Step 6)PropertyChangedをサブスクライブ(Step 6)ComparisonItems.Clear()が呼ばれること| ファイル | 目的 | レイヤー |
|---|---|---|
ComparisonItemViewModel.cs | スコア+背景色付き単一比較行 | ViewModel |
ComparisonTabViewModel.cs | 親コレクション+エクスポートゲート | ViewModel |
ComparisonView.xaml | ItemsControl付き3カラムレイアウト | View |
| 色 | 16進 | 適用タイミング |
|---|---|---|
| 🆕 ピンク | #F8D7DA | 不一致:ソースA ≠ ソースB |
| ✅ グリーン | #BBF7D0 | ユーザーが検証チェックボックスをチェック |
| ❌ レッド | Red | スコア < 60% |
| オレンジ | Orange | スコア 60–79% |
| グリーン | Green | スコア ≥ 80% |
| 透明 | Transparent | フィールドが一致(ハイライトなし) |
| イエロー | #FFFFCC | 編集可能フィールドの背景 |
dotnet-generic-matching — このビューで表示する結果を生成するマッチングサービスdotnet-wpf-pdf-preview — 比較結果と並べて表示するPDFプレビューパネル| バージョン | 日付 | 変更内容 |
|---|---|---|
| 1.0.0 | 2025-07-13 | 🆕 初回リリース — 不一致ハイライト付きサイドバイサイド比較ビュー |