22575


WPFのInkCanvasで、EditingModeがSelectの時、Selection系イベント（SelectionChanging/SelectionChanged）内でEditingModeを変更しようとすると以下のエラーが発生していました。

> 型 'MS.Internal.Ink.SelectionEditor' のオブジェクトを型
> 'MS.Internal.Ink.StylusEditingBehavior' にキャストできません。

xaml

[code]

        <InkCanvas Name="hoge" EditingMode="Select"  SelectionChanged="hoge_SelectionChanged" SelectionChanging="hoge_SelectionChanging">
            <Rectangle Width="100" Height="100" Fill="Aqua"></Rectangle>
        </InkCanvas>
    
[/code]

c#  
下記のコードのままだと、SelectionChangingのところでエラーが発生します。  
SelectionChangingをコメントアウトすると、今度はSelectionChangedのところでエラーが発生します。

[code]

        private void hoge_SelectionChanged(object sender, EventArgs e)
        {
            this.hoge.EditingMode = InkCanvasEditingMode.None;
        }
    
        private void hoge_SelectionChanging(object sender, InkCanvasSelectionChangingEventArgs e)
        {
            this.hoge.EditingMode = InkCanvasEditingMode.None;
        }
    
[/code]

**実現したいこと**
は、InkCanvasのChildrenに追加したオブジェクトのうち、特定のオブジェクトのみ、選択時（そのオブジェクトにマウスが押されたとき）の動作を変えたいと思っています。

いったんは以下の方向性で対応する予定です。  
EditingModeがSelectの場合は、MouseDownイベントが発生しないため、PreviewMouseDownイベントとVisualTreeHelper.HitTestを利用して、マウス位置にあるオブジェクトを特定し処理を分岐する。

もし、 **実現したいこと** と似たような処理を別の方法で対応された方がいるようでしたら、またその他気になる点などありましたら、補足いただければ幸いです。

  * NET Framework 4.5.2
  * Visual Studio 2015


CC BY-SA 3.0
2016-02-26T13:52:31.717
22573
2016-02-26T14:40:30.850
2016-02-26T14:00:17.287
14569
14569
question
c# visual-studio wpf
InkCanvasのSelection系イベントにおけるEditModeの変更


例外発生箇所は[ここ](http://referencesource.microsoft.com/#PresentationFramework/src/Framework/MS/Internal/Ink/EditingCoordinator.cs,574c12a42f90586d,references)ですね。実装からするとMSの不具合のような印象を受けるので報告したほうが良いかもしれません。

回避策ですが、`PreviewMouseDown`では動作の見た目が変わってしまうので、`SelectionChanging`で

[code]

    Dispatcher.BeginInvoke(
        (Action)(() => this.hoge.EditingMode = InkCanvasEditingMode.None),
        DispatcherPriority.Render
    );
    
[/code]

のように非同期処理を開始するのがよいと思います。

また`EditMode`の変更ではなく選択をキャンセルするのが主目的なのであれば、同イベントの`EventArgs`を使用して

[code]

    e.Cancel = true;
    
[/code]

もしくは

[code]

    e.SetSelectedStrokes(new StrokeCollection());
    e.SetSelectedElements(Enumerable.Empty<UIElement>());
    
[/code]

でユーザーの選択を変更することができます。


CC BY-SA 3.0
2016-02-26T14:40:30.850
22575
2016-02-26T14:40:30.850
5750
22573
answer