前置きの前置き・・・
25日の投稿がされていなかったので代わりに投稿します。
前置き・・・
前回の投稿から何万年経ったことでしょう。
忙しいのにブログを書き続けられている人って本当にすごい。いつ寝てるの?
さて、今回個人アプリを全てAI(Cursor)で作り上げたのでそのときに嵌ったことなどを書きたいと思います。
目次
1.作りたいアプリ
2.仕様を細かく伝えないと脱線する
3.仕様を細かく伝えないと、修正→デグレ→修正→デグレ・・・の罠に陥る
4.プランの上限に達しそうな場合は警告が出るし、反応も遅くなる
5.完成したアプリ
1.作りたいアプリ
Windows11の標準エクスプローラーよりも高速で動くアプリを作りたいと思いました。
標準エクスプローラーは全体的に遅いし、右クリックメニューの表示がめちゃくちゃ遅い。
標準エクスプローラーに近いUIのアプリもありますが、やっぱりもっさりしていて使いづらい。
タブ機能を持ったアプリもありますが、Windows11風でない。
なので、Windows11風でかつ高速に動作する+αの機能を持ったエクスプローラーを作る事にしました。
2.仕様を細かく伝えないと脱線する
一から作るのは時間が掛かってしまうのでCursorに指示して作ることにしました。
この判断は良かったと思います。
以降、Cursorとのやり取りを載せたいと思います。
前提としてWPF-UIを使ったこんな感じのUIです。

↑のWPF-UIを使って↓のエクスプローラーを作るように指示しました。
**わたし**
ナビゲーションをクリックしても切り替わったことが分からないです。
タブもクリックしたときどのタブが開いているタブか分からないです。
**Cursor**
ナビゲーションとタブの視覚的フィードバックを改善するため、`ExplorerPage.xaml` を確認中です。
タブとナビゲーションの視覚的フィードバックを改善します。現在のスタイルを確認し、選択状態を明確にします。
タブとナビゲーションの視覚的フィードバックを改善中です。
リンターエラーを確認中です。
視覚的フィードバックを改善しました。変更点は以下の通りです。
## 改善内容
### 1. **タブの選択状態を明確化**
- 選択されたタブにアクセントカラー(`AccentFillColorDefaultBrush`)を適用
- 下線を2pxに増やして選択状態を強調
- 選択されたタブにマウスオーバー時の色も追加
### 2. **ナビゲーションボタンの視覚的フィードバック**
- ホーム、戻る、更新、お気に入り追加ボタンに以下を追加:
- マウスオーバー時:背景色を変更
- クリック時(`IsPressed`):アクセントカラーでフィードバック
### 3. **クイックアクセスアイテムの視覚的フィードバック**
- ピン留めフォルダー、ドライブ、最近使用したファイルに以下を追加:
- マウスオーバー時:背景色を変更し、アクセントカラーのボーダーを表示
これにより、タブの選択状態とナビゲーション操作の視覚的フィードバックが明確になります。アプリを実行して確認してください。
※これは、左のナビゲーション(ツリービューみたいないやつ)をクリックしたときやタブをクリックしたときに、どのタブがアクティブなのか分からないのでアクティブなタブは色を変えて欲しいという意図がありました。
**わたし**
ナビゲーションペインのアイコンをクリックしても反応がないです。
**Cursor**
ナビゲーションペインのアイコンが反応しない原因を確認中。MainWindowのナビゲーション実装を確認します。
MainWindowのコードビハインドを確認中。
エクスプローラーページのアイテムの`Content`が空で、NavigationViewのイベントハンドラーが未設定の可能性があります。修正します。
エクスプローラーページのアイテムに`Content`を設定し、NavigationViewのイベントハンドラーを追加します。
NavigationServiceの取得方法を修正し、リンターエラーを確認中。
コンストラクタで受け取ったNavigationServiceをフィールドに保存して使用するように修正中。
修正を完了しました。変更点は以下の通りです。
## 修正内容
### 1. **エクスプローラーページのアイテムにContentを設定**
- `Content`を空文字列から「エクスプローラー」に変更
- クリック時のフォールバック処理を追加
### 2. **NavigationViewのItemInvokedイベントハンドラーを追加**
- `MainWindow.xaml`に`ItemInvoked`イベントを追加
- `MainWindow.xaml.cs`にイベントハンドラーを実装
- `TargetPageType`が設定されているアイテムをクリックしたときに、NavigationServiceでナビゲート
### 3. **NavigationServiceの保持**
- コンストラクタで受け取った`INavigationService`をフィールドに保存し、イベントハンドラーで使用
これで、ナビゲーションペインのアイコンをクリックしたときに、エクスプローラーページに正しくナビゲートされるはずです。アプリを実行して確認してください。
**わたし**
ビルドエラーです。
**Cursor**
ビルドエラーを確認中です。
ビルドを実行してエラーを確認中です。
`NavigationViewItemInvokedEventArgs`の型名が誤りです。正しい型名を確認中です。
WPF UIのNavigationViewのItemInvokedイベントの正しい型を確認中です。
型名を確認し、`object`型を使用するか、イベントハンドラーを簡略化します。
ビルドエラーを解消しました。
`NavigationViewItemInvokedEventArgs`型が存在しないため、イベントハンドラーの引数を`object`型に変更しました。WPF UIのNavigationViewは`TargetPageType`に基づいて自動的にナビゲートするため、イベントハンドラー内での追加処理は不要です。お気に入りアイテムなど、`Click`イベントが設定されているアイテムはViewModelで処理されます。
ビルドは成功し、警告のみです。アプリを実行して、ナビゲーションペインのアイコンが正しく動作するか確認してください。
**わたし**
ナビゲーションの選択状態が変わらないです。
**Cursor**
ナビゲーションペインの選択状態が更新されない原因を確認中。NavigationViewの選択状態管理を確認します。
NavigationViewの選択状態を更新する処理を追加中。ItemInvokedイベントで選択状態を設定します。
NavigationViewの選択状態を更新する処理を追加中。ItemInvokedイベントで選択状態を設定します。
NavigationViewItemのClickイベントでも選択状態を更新するよう修正中。ViewModelからMainWindowにアクセスできるようにします。
必要なusingディレクティブを追加中。
`SelectedItem`が読み取り専用のため、`NavigationViewItem`の`IsSelected`を直接設定する方法に切り替えます。
`IsSelected`プロパティは存在しません。WPF UIのNavigationViewの自動選択に合わせ、Clickイベントを削除し、ItemInvokedイベントで処理するように変更します。
必要なusingディレクティブを追加中。
ビルドは成功しました。変更点は以下の通りです。
## 修正内容
1. **エクスプローラーアイテムのClickイベントを削除**
- `TargetPageType`が設定されているため、NavigationViewが自動的にナビゲートと選択状態を管理します
2. **ItemInvokedイベントでお気に入りアイテムを処理**
- お気に入りアイテム(Tagにパスが設定されている)をクリックしたときに、ItemInvokedイベントで処理するように変更
- これにより、NavigationViewの自動選択機能が機能します
3. **必要なusingディレクティブを追加**
- `System`、`System.Threading.Tasks`、`System.Windows`を追加
WPF UIのNavigationViewは、`TargetPageType`が設定されているアイテムをクリックしたときに、自動的に選択状態を更新します。エクスプローラーアイテムは`TargetPageType`が設定されているため、自動的に選択状態が更新されます。
お気に入りアイテムは`TargetPageType`がないため、ItemInvokedイベントで処理します。NavigationViewはItemInvokedイベントが発火したときに、選択状態を自動的に更新するはずです。
アプリを実行して、ナビゲーションペインの選択状態が正しく更新されるか確認してください。
**わたし**
ナビゲーションのホームは「ホーム」という文字列は表示したままでOKです。
**Cursor**
ナビゲーションペインの「エクスプローラー」を「ホーム」に変更します。
変更を反映しました。ナビゲーションペインの「エクスプローラー」を「ホーム」に変更しました。
ビルドは成功しています。アプリを実行すると、ナビゲーションペインに「ホーム」と表示されます。
**わたし**
ナビゲーションの「ホーム」の文字列がきえてしまいます。
**Cursor**
ナビゲーションの「ホーム」が消える原因を確認中。コードを確認します。
WPF UIのNavigationViewでは、`Content`が表示されない場合があります。`Header`を使用するか、`ContentTemplate`を設定して表示を確認します。
WPF UIのNavigationViewItemでは、`Content`が表示されない場合があります。`Header`も設定するか、`ContentTemplate`を使用します。まずは`Header`を設定します。
ビルドは成功しました。`Content`に`TextBlock`を設定することで、「ホーム」が表示されるはずです。
これでも表示されない場合は、NavigationViewの`PaneDisplayMode`が`LeftFluent`でペインが折りたたまれている可能性があります。その場合は、ペインを展開すると「ホーム」が表示されます。
アプリを実行して確認してください。まだ表示されない場合は、お知らせください。
**わたし**
消えますね。
**Cursor**
「ホーム」が消える原因を調査中。お気に入りアイテムと同じ方法で設定し、NavigationViewの動作を確認します。
お気に入りアイテムと同じく、文字列を直接設定する方法に切り替えます。`TargetPageType`が設定されている場合の動作も確認します。
`Loaded`イベントだけでは不十分な可能性があるため、`PropertyChanged`イベントでContentの変更を監視し、必要に応じて再設定する方法に切り替えます。
必要なusingディレクティブを追加中。
ビルドは成功しました。`DependencyProperty`の変更を監視し、Contentがクリアされた場合に「ホーム」を再設定するようにしました。
これでも表示されない場合は、WPF UIのNavigationViewが`TargetPageType`設定時にContentを自動クリアしている可能性があります。その場合は、`TargetPageType`を設定せず、`ItemInvoked`イベントで手動ナビゲートする方法に切り替えます。
アプリを実行して確認してください。まだ表示されない場合は、お知らせください。別の方法を試します。
**わたし**
最初は表示されていますが、右のペインが表示されたらきえてしまいます。
**Cursor**
右ペイン表示時にContentがクリアされる問題を修正します。`TargetPageType`を外し、`ItemInvoked`で手動ナビゲートする方法に切り替えます。
`TargetPageType`を削除し、`ItemInvoked`で手動ナビゲートするように変更します。ホームアイテムの識別には`Tag`を使用します。
ビルドは成功しました。変更点は以下の通りです。
## 修正内容
1. **`TargetPageType`を削除**
- `TargetPageType`を設定しないことで、NavigationViewがContentを自動的にクリアしないようにしました
2. **`Tag`でホームアイテムを識別**
- ホームアイテムに`Tag = "HOME"`を設定し、`ItemInvoked`イベントで識別できるようにしました
3. **`ItemInvoked`イベントで手動ナビゲート**
- ホームアイテムがクリックされたときに、`ItemInvoked`イベントで手動でエクスプローラーページにナビゲートするようにしました
これにより、右のペインが表示された後も「ホーム」の文字列が消えなくなります。`TargetPageType`を設定しないことで、NavigationViewがContentを自動的にクリアする動作を回避しています。
アプリを実行して確認してください。「ホーム」の文字列が右のペインが表示された後も表示され続けるはずです。
**わたし**
OKです。
**Cursor**
ホーム以外のページからホームをクリックしても切り替わらない問題を確認中。`ItemInvoked`の処理を確認します。
ホームアイテムにClickイベントを追加し、確実にナビゲートするようにします。また、既にExplorerPageにいる場合でもホームページを表示するようにします。
ホームアイテムにClickイベントを追加し、確実にナビゲートするようにします。既にExplorerPageにいる場合でもホームページを表示するようにします。
漸く思い通りのものができました。
ここまで何往復したことでしょう。
今、もう一度やるとすれば、これだけで良かったはずです。
ナビゲーションウィンドウの中に、
単一ペインもしくは分割ペインにそれぞれタブがあり、その中にListViewがあります。
ナビゲーションのホームボタンをクリックしたときにアクティブなタブの内容をホーム画面にしてください。
3.仕様を細かく伝えないと、修正→デグレ→修正→デグレ・・・の罠に陥る
下記に示すようにこれぐらい一気に伝えないと、あっちは上手く行っても、こっちは動かなくなる・・・ということが結構発生します。
-
共通仕様
1-1. コピーや移動先に同じファイル名やフォルダー名がある場合は確認ダイアログを表示し、上書きするかどうかを確認してください。「はい」「いいえ」「すべて『はい』」という選択肢も必要です。
1-2. 複数のファイルやフォルダーであってもコピーや移動が行えること -
ドラッグ&ドロップ機能
2-1. 単一ペインのときアプリの外から(例えばデスクトップなどから)ドラッグ&ドロップしたときドライブが異なればファイルまたはフォルダーをコピーする。ドライブが同じ場合ファイルまたはフォルダーは移動する。
2-2. 分割ペインのときであってもアプリ外からドラッグ&ドロップしたときドライブが異なればファイルまたはフォルダーをコピーする。ドライブが同じ場合ファイルまたはフォルダーは移動する。
2-3. 分割ペインで、ペイン間でドラッグ&ドロップしてもドライブが異なればファイルまたはフォルダーをコピーする。ドライブが同じであればファイルまたはフォルダーを移動する。 -
コピー&ペースト(Ctrl+C/V)機能
3-1. アプリ内外で Ctrl+C でコピーされたファイルやフォルダーは、Ctrl+Vで単一ペインのタブや分割ペインの左右のタブに貼り付けることが可能である。アプリ内で Ctrl+C でコピーしたファイルやフォルダーは、Ctrl+V でアプリ外に貼り付けることが可能である。 -
切り取りと貼り付け(Ctrl+X/V)機能
4-1. アプリ内外で Ctrl+X で切り取られたファイルやフォルダーは、Ctrl+V で単一ペインのタブや分割ペインの左右のタブに貼り付けることが可能である。
4-2. アプリ内で Ctrl+X で切り取ったファイルやフォルダーは、Ctrl+V でアプリ外に貼り付けることが可能である。ただし、ドライブが異なる場合はファイルやフォルダーをコピーすることとする。 -
タブの更新について
5-1. FileSystemWatcherを使いタブ内のファイルやフォルダーの増減を監視し、変化があった場合、タブを更新する。このとき、プログレスリングは表示しなくてよい。 -
削除機能
6-1. 単一、複数に関わらず選択したファイルやフォルダーは削除できること(※ゴミ箱に移動)
6-2. フォルダー内にファイルやフォルダーがあっても削除できること
4.プランの上限に達しそうな場合は警告が出るし、反応も遅くなる
プランごとに上限が決まっているようで、近づいてくるとVPNの接続エラーっぽいものが頻繁に発生します。

また、Pro+プランにアップグレードすることを促すメッセージが表示されることもあります。

他にも、前に出来ていたことがなぜかできなくなっている場合ということもしばしばあります。
そこはテストの自動化でカバーしたいところですが、UIに関連したテストの自動化って難しいんですよね・・・
それこそCursorにテストコードを書かせればいいんだけど。
5.完成したアプリ
Fast Explorerは、試行錯誤しながら一からCursorで作ったアプリです。
今後もCursorを使ってアプリを作って行きたいと思います。
現在Christmasセール中です!Pro+版は月額$60なので出費が痛いです・・・
カンパしていただける方はぜひお願いいたします。(※買い切りです)
