Viewerのバージョン0.9.2.10を公開しました。プレビュー領域中の任意の場所をクリックすると、その位置を領域内に含んでいるウィンドウハンドルを列挙する機能を追加しました。0と1の世界の見習い探検家http://www.a32kita.tk/software/winhandlevw/では。a32kitaTextWriter系クラスで最後まで内容が反映されないというトラブルの対処法についてご紹介いたします。対して、データの書き込みを行うために提供されるクラスです。名前空間で提供されております。BinaryWriterプリミティブ型をバイナリでストリームに書き込みます。特定のエンコーディングの文字列の書き込みをサポートします。MSDNこれらのクラス全般で発生しうるトラブルのお話です。標準的なTextWriter系クラスは、Streamへの書き込みのトランザクションで発生するオーバーヘッドの軽減のため、内部でのバッファリング機能が実装されております。ある程度のデータがTextWriterのインスタンス内でバッファリングされたのち、Streamへ実際の書き込みが行われます。TextWriter系クラスからStreamへ内部バッファの書き込みが行われる前にプログラムが終了してしまうなどすると、バッファされたデータは消失します。CloseメソッドとFlushメソッドTextWriter系クラスには、Stream系クラス同様「Close」メソッドが実装されております。このメソッドは、ターゲットになっているStreamをクローズするものでありますが、実はそれだけではありません。TextWriterでCloseを実施する際、内部ではStreamをCloseする前に先程紹介したバッファをStreamへ書き込む処理もおこなっております。プログラムやスレッドが終了する前にCloseまで実施されていれば、正しくバッファの反映処理まで実行されます。このClose処理は、TextWriter.Dispose()でも実行されるため、usingセクションでTextWriterを使用するなどの方法でバッファを反映されることも可能です。バッファの反映処理は、Closeメソッド内以外でも単独で提供さております。それがFlushメソッドです。CloseメソッドではFlushメソッドとStreamのCloseメソッドが実行されているということになります。AutoFlushプロパティTextWriterには、AutoFlushプロパティが用意されております。このプロパティはbool型の値を取り、デフォルトではfalseです。このプロパティにtrueを設定すると、Write系メソッドが実行される度にFlush処理が実行されるようになります。書き込み処理でのオーバーヘッドが大きいタイプでのStreamでは、パフォーマンスに大きな影響が出てしまいますが、、まとめ原則としてTextWriterは必ずスレッドまたはプログラム終了前にCloseしましょう。Closeを行う前にStreamに対してすべての書き込みを反映させる必要がある場合は、FlushメソッドやAutoFlushプロパティを活用しましょう。a32kita1年ぶりの新しいソフトの公開です。Viewerは、お使いのWindowsでデスクトップ上に展開されているウィンドウのハンドル情報を閲覧すためのツールアプリケーションです。ウィンドウハンドルの値、ウィンドウの名前、クラス名、位置と大きさを確認することが出来ます。Win32の標準的なコントロールを使用しているウィンドウでは、ウィンドウ上に配置されたコントロールにもウィンドウハンドルが割り当てられており、本ソフトウェアではこれらのコントロールのハンドル情報も確認することが可能です。こちらのページからダウンロード可能です。0と1の世界の見習い探検家http://www.a32kita.tk/software/winhandlevw/では。設定することはできません。スコープ内にあり、この要素には、別のスコープで定義されたときに既に名前が登録されています。考察についてご紹介いたします。発生状況このビルドエラーには次の状況で遭遇しました。(図3)なかなか既存のPanel系コントロールを強引に拡張する機会がまず少ないですが、だからなのかこのエラーに関する情報も見つからなかったので、あえて書いておきます。対処法すべてのビルドエラーMC3093が同じ原因により発生しているという保証ができないので、なんとも言えませんが、とりあえず上記状況で発生したものに関しては、次の方法で対処しました。対処法は、2つあります。x:Nameの付与をやめる拡張したPanel系コントロールの利用側で、追加したコントロールへのx:Nameをしなければ、このビルドエラーは回避できます。不要ならば削除してしまいましょう。拡張時にXAMLを使用しないこの方法は、ざっくり言えばPanel系コントロールを拡張する際に図2のようなXAMLを使用しないことです。私がこの例外に陥った時は、XAMLとコード混みでGridなどを継承して拡張をおこなっておりました。実際の拡張の実装はすべてコードでやっていたので本当はXAMLは不要だったんです。削除したら、問題は解決しました。原因の考察Panel系コントロールを拡張する際、XAMLソースも混みでやってしまうと、その拡張したコントロールに添付されているXAMLファイル側でコントロールの追加が可能になります。エラーメッセージの言う「別のスコープ」とは恐らく、この拡張時に作ってしまったXAMLファイルのことを指しているのかと。わかりませんんが、拡張側のXAMLスコープと利用側のXAMLスコープの両方でx:Nameが付与されることを警戒しているのがこのビルドエラーなのかなと。言って原因はよくわからないのが現状です...。その他Panel系コントロールを継承して拡張するのはあまり正攻法とされていないようですので、もっと別の手段で拡張したほうが良さそうですね。a32kita先日取り上げた、「ObservableCollection」でClearメソッド実行直前まで代入されていたアイテムたちを、CollectionChangedで取得するお話の続きです。7:21)https://blogs.yahoo.co.jp/a32kita/15752321.htmlこんなの実装してみました。a32kita/ExtendedObservableCollectionhttps://github.com/a32kita/ExtendedObservableCollectionちょっとその解説を...。先行研究「ObservableCollectionの拡張」まず、CollectionChangedイベントでClearメソッドされる直前の中身を取得する方法として、前回の記事の最後でObservableCollectionを継承した拡張クラスの実装についてご紹介致しました。前回の記事は、結果としては未解決のまま終了してしまいました。失敗の主な理由は、CollectionChangedのイベントデータ格納型であるNotifyCollectionChangedEventArgsクラスでは、ActionにコレクションのClearを表す「Reset」を設定したとき、変更されたアイテムの一覧を表すChangedItemsには何も設定が行えない、というところにありました。NotifyCollectionChangedEventArgsのコンストラクタにResetを設定した状態で、ChangedItemsの設定を行おうとしてしまうと、ArgumentExceptionを吐かれてしまいます。NotifyCollectionChangedEventArgs.OldItemsにReset前のコレクションの中身を放り込む行為は、.NETを創造した神様たちがお許しにならないということのようです。神様の思し召しとなれば仕方がありません。それが天啓というのであれば、我々は抗うべきではありません。OldItemsにデータを格納するのは諦めましょう。いうわけで、ObservableCollectionの拡張に加え、もう1つ拡張することにしました。提案手法「NotifyCollectionChangedEventArgsの拡張」まず前回の記事の末尾で述べた通り、ObservableCollectionを拡張した「ExtendedObservableCollection」なるものを定義しました。ObservableCollectionを継承し、protectedなメソッド、ClearItemsをオーバーライドすることで、Clear時の処理を変更します。これだけではCollectionChangedを通して、Clear実行前のコレクションの内容を通知することはできません。OldItemsではなく、NotifyCollectionChangedEventArgsに新しいプロパティを作ってしまえば良いというのが今回の提案手法です。既存のNotifyCollectionChangedEventArgsを拡張するという手段を選んだのは、CollectionChangedイベントとの互換性を保つためです。定義したExtendedObservableCollectionChangedEventArgs名前を付けるのが下手で、えらく長い名前になってしまいました。名前をつけるのが得意な方、新しい名前を付けてやって下さい。このクラスの特長は、OldItems、NewItemsに加え「PreviousItems」という名前のプロパティを有しているというところです。ExtendedObservableCollectionでは、Clear時にこのPreviousItemsにそれまでの内容を格納します。NotifyCollectionChangedEventArgsの子クラスであるため、CollectionChangedイベントでイベントデータとして飛ばすことが可能です。CollectionChangedをハンドルする際に必要に応じてNotifyCollectionChangedEventArgs型のイベントデータをExtendedObservableCollectionChangedEventArgs型へキャストしていただく必要がありますが。その他拡張List<T>では利用できるのにObservableCollection<T>では利用できなかったAddRangeをExtendedObservableCollection<T>では実装しました。Clear時の挙動は完全にオーバーライドしてしまっている都合上、正しく動作するかわからないんですよね。Clear直後のCollectionChanged発生時のイベントデータ一応正しくデータは受け取れているようですが、WPFなんかに利用するために実装したPropertyChangedの挙動に不安が。WPFのMVVMの中でお使いになる際は、ClearとAddRangeの挙動にご注意下さい。私のほうでも気がついたら適宜修正します。最後に名前がクソなクラスを定義してしまいましたが、一応前回の記事の解決編ということにはなったのではないでしょうか。一応今回この記事で取り上げているプログラムは完全ライセンスフリーと宣言しておきます。使えると思った方、もしいらっしゃいましたらご自由にお使い下さい。