markdown を HTMLに変換するアプリ MdHTMLer を更新しました。
変更点 Ver 0.1 → Ver 1.0
- 日本語対応(一部)
- 目次ページのタイトルを指定できるようにした
- md以外をコピーしないオプション追加
現状
大量ファイルは処理できず、途中で落ちる・・・
以上
markdown を HTMLに変換するアプリ MdHTMLer を更新しました。
大量ファイルは処理できず、途中で落ちる・・・
以上
自分用:メモ:
非同期で再帰(UWP)の挙動が安定しない…。
この辺か???
自分でも書いてはみたが...
var buf = new BlockingCollection<IStorageItem>(); var copyDirTask = Task.Run<Task>(async () => { await this.CopyFolderAsync(s, d, buf); buf.CompleteAdding(); }); List<AbstractStorage> result1 = new List<AbstractStorage>(); var outputTask = Task.Run(() => { foreach (var item in buf.GetConsumingEnumerable()) { Debug.WriteLine(item.Path); result1.Add(new AbstractStorage() { Path = item.Path, Storage = item }); } }); await Task.WhenAll(copyDirTask, outputTask); // 再帰 private async Task CopyFolderAsync(StorageFolder sourceContainer, StorageFolder destContainer, BlockingCollection<IStorageItem> buf) { var subDirBufs = new List<BlockingCollection<IStorageItem>>(); StorageFolder destDir = await destContainer.CreateFolderAsync(sourceContainer.Name, CreationCollisionOption.OpenIfExists); buf.Add(destDir); // ファイル var files = await sourceContainer.GetFilesAsync(); foreach (var file in files) { var copied = await file.CopyAsync(destDir, file.Name, NameCollisionOption.ReplaceExisting); buf.Add(copied); } // 非同期で再帰 var tasks = new List<Task>(); var folders = await sourceContainer.GetFoldersAsync(); foreach (var folder in folders) { var bufSubDir = new BlockingCollection<IStorageItem>(); tasks.Add(Task.Run(async () => { Debug.WriteLine(folder.Path); await CopyFolderAsync(folder, destDir, bufSubDir); bufSubDir.CompleteAdding(); })); subDirBufs.Add(bufSubDir); } await Task.WhenAll(tasks).ContinueWith(task => { foreach (var subDirBuf in subDirBufs) { foreach (var item in subDirBuf.GetConsumingEnumerable()) { Debug.WriteLine(item.Path); buf.Add(item); } } }); return; }
Microsoft パートナー センターで「パッケージ ファミリ名が無効です」のエラーが出た
Microsoft パートナー センター> アプリ > パッケージ:
===
提出する前に、すべてのパッケージ検証エラーを修正する必要があります。
===
UWPプロジェクト>マニフェスト>パッケージ化>公開者>証明書の選択>その他
で、エラーメッセージにあった 期待値っぽい方を選択し、再ビルド。
ストアから選択
別のが選択されているので:
正しそうな方を再選択
解消された。
WindowsTemplateStudio 4.0.2
4.0.2 がリリースされてました
App (WinUI 3 in Desktop)が追加されてる!
機能拡張から更新
プロジェクトを作成
App(WinUI 3 in Desktop) が追加されてる
1:種類
blank は 必要最低限のシンプル構成っぽい。
Navigation Pane の方だと、Windows Community Toolkitが入ってくる。(左側のメニューも動的に変わる)
今回は、Navigation Paneですすめる。
2:Design pattern
1つだけ
3:ページ
今使えるのは6つ
4:機能
インストーラーとかテーマとか
メインのプロジェクトと、Coreのプロジェクト、それとパッケージプロジェクト
依存関係:
Reunionがいらっしゃる!
基本はWPF(だよね??)
フレームワークは .net5 + Windows バージョン指定してるやつだ。
TFM(Target Framework Moniker)
ViewModel で Di 使ってたり、
ページ遷移の為の処理等、おなじみの奴らが既にいる。
(自分にはちょっと重い)
警告バーが一杯 出てた。
> これはVisualStudioを再起動したら消えた。
実行! エラー! 無視して続行!
(スクショ 撮り逃した)
起動した!
以上
ファイル優先のファイル一覧に並び替えたい
こんな感じに階層になっているファイル一覧をとってきた。
なぜか「ファイル名」でソートされてしまっている...。
// temp に一覧データが入っている Debug.WriteLine(string.Join("\r\n", temp)); C:\root\300\1.md C:\root\300\2.md C:\root\200\200_10\200_1.md C:\root\200\200_20\200_1.md C:\root\200\200_10\200_2.md C:\root\200\200_20\200_2.md C:\root\200\200_20\200_3.md C:\root\200\200_20\200_4.md C:\root\README.md C:\root\releasenotes.md C:\root\400\Sample.md C:\root\100\top.md
取得済の一覧を、パス順で並び替えた一覧に並び替えたい。
ただし、同一階層内では「フォルダ(の中)」よりも「ファイル」を優先とする。
(取得する方はコード変更できない)
下記で希望した形になった。
もう少しスマートにならないものか。
var t3 = temp.GroupBy(x => System.IO.Path.GetDirectoryName(x)) .OrderBy(f => f.Key) .SelectMany(x => x.OrderBy(f => f)); Debug.WriteLine(string.Join("\r\n", t3)); C:\root\README.md C:\root\releasenotes.md C:\root\100\top.md C:\root\200\200_10\200_1.md C:\root\200\200_10\200_2.md C:\root\200\200_20\200_1.md C:\root\200\200_20\200_2.md C:\root\200\200_20\200_3.md C:\root\200\200_20\200_4.md C:\root\300\1.md C:\root\300\2.md C:\root\400\Sample.md
パスでソート
これだと、ファイル(README.md)が末尾に並んでしまう…。
var t1 = temp.OrderBy(x => x); Debug.WriteLine(string.Join("\r\n", t1)); C:\root\100\top.md C:\root\200\200_10\200_1.md C:\root\200\200_10\200_2.md C:\root\200\200_20\200_1.md C:\root\200\200_20\200_2.md C:\root\200\200_20\200_3.md C:\root\200\200_20\200_4.md C:\root\300\1.md C:\root\300\2.md C:\root\400\Sample.md C:\root\README.md C:\root\releasenotes.md
第一ソートキーに 階層数(の代わりに区切り文字数)
第二ソートキーに パス
駄目でした。(そりゃそうか・・・)
var t2 = temp.OrderBy(x => (x.Where(c => c == '\\')).Count()).ThenBy(f => f); Debug.WriteLine(string.Join("\r\n", t2)); C:\root\README.md C:\root\releasenotes.md C:\root\100\top.md C:\root\300\1.md C:\root\300\2.md C:\root\400\Sample.md C:\root\200\200_10\200_1.md C:\root\200\200_10\200_2.md C:\root\200\200_20\200_1.md C:\root\200\200_20\200_2.md C:\root\200\200_20\200_3.md C:\root\200\200_20\200_4.md
以上
UWPのドラッグドロップ関連の処理は、下記から拝借。
https://docs.microsoft.com/ja-jp/windows/uwp/design/windows-template-studio/
↑ のファイルをコピペ ※ ネームスペースを適当に修正
共通プロジェクトのView <Frame x:Name="TopFrame"> <xct:DockLayout> <Entry x:Name="EntryTop" Text="{Binding Path=SourcePath, Mode=TwoWay}" > </Entry> </xct:DockLayout> </Frame> ・・・略
共通プロジェクトのViewModel public class MainViewModel : BaseViewModel { private string sourcePath = string.Empty; public string SourcePath { get { return this.sourcePath; } set { SetProperty(ref sourcePath, value); } } private string targetPath = string.Empty; public string TargetPath { get { return this.targetPath; } set { SetProperty(ref targetPath, value); } } ・・・略
ここまでは特に特別な箇所はない。
通常だと、共通プロジェクトでFrameをサブクラス化したカスタムコントロールを作成する・・・んだけど、今回は横着して省略。
UWPドロップ用のファイルを追加しとく
カスタムレンダラー クラス: [assembly: ExportRenderer(typeof(Xamarin.Forms.Frame), typeof(CustomFrameRenderer))] namespace MyFormPrj.UWP.CustomViews { public class CustomFrameRenderer : FrameRenderer ・・・略
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e) { base.OnElementChanged(e); // ドロップ可 this.Control.AllowDrop = true; // ドロップ処理を作成 var fileDropCmd = new ReactiveCommand<IReadOnlyList<IStorageItem>>().WithSubscribe(x => this.OnGetStorageItem(x)); // D&D を登録 DragDropService.SetConfiguration(this.Control, new DropConfiguration() { DropStorageItemsCommand = fileDropCmd }); return; }
public void OnGetStorageItem(IReadOnlyList<IStorageItem> items) { foreach (var item in items) { switch (this.Element.StyleId) { case "TopFrame": { Xamarin.Forms.Entry entryElement = this.Element.Content.FindByName("EntryTop") as Xamarin.Forms.Entry; // コントロールに直接格納 entryElement.Text = item.Path; break; } case "BottomFrame": { Xamarin.Forms.Entry entryElement = this.Element.Content.FindByName("EntryBottom") as Xamarin.Forms.Entry; // (フォーム側で)バインドしているモデルに格納 var model1 = entryElement.BindingContext as MyFormPrj.ViewModels.MainViewModel; model1.TargetPath = item.Path; break; } default: break; } // for文に意味はない break; } }
渡し方1:entryElement.Text(←共通プロジェクトのEntryのテキスト) = item.Path(UWPでドロップされたファイルパス)
バインドしているモデルに(無理くり?)アクセスしてもいい(のか?)