ReactiveProperty で TextBox に対して Drop 処理が出来ない!?
結論:
引数のEventArgs の値を変更する必要がある場合は、Prismのイベント発火「prism:InvokeCommandAction」を利用する
引数のEventArgs の値を参照しかしない場合は、Reactiveのイベント発火「rpi:EventToReactiveCommand」を利用する
Prismは「xmlns:prism="http://prismlibrary.com/" 」
Reactiveは「xmlns:rpi="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"」
色々やった事:
TextBox に対してファイルをドロップさせファイルパスを表示する。
といういたってシンプルなものを作ろうとしたが、ReactiveProperty で作れない…なぜだ!
って事でとりあえず動かないソース:(一部抜粋)
MainPage.xaml:
MainPageViewModel:
何がダメか:
1.DoPreviewDragOver メソッドに処理が来るが、Handled と Effects に値を設定しても、反映されていないっぽい。
⇒ 結果、画面のマウスマークは禁止マークから変更されない。
2.上記より、DoDropFile メソッドが呼び出されない。
ちなみに「コードビハインド(*.xaml.cs) でイベントを記載した所、同じ処理でも正常に動作する」てな感じです。
で、悩むこと数日… たまたま Reactiveで有名(本家)な かずきさん のページをぼーっと眺めていると
ここ:https://blog.okazuki.jp/entry/2019/04/19/172010
Reactive でのイベント発火方法と、Prismのイベント発火方法が記載されているではないですか…
まさかね…と思いつつ下記を変更(XAML)
修正前:(Reactive で送信する方法)
修正後:(Prismで送る方法)
引数のEventArgs の値を変更する必要がある場合は、Prismのイベント発火「prism:InvokeCommandAction」を利用する
引数のEventArgs の値を参照しかしない場合は、Reactiveのイベント発火「rpi:EventToReactiveCommand」を利用する
Prismは「xmlns:prism="http://prismlibrary.com/" 」
Reactiveは「xmlns:rpi="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"」
色々やった事:
TextBox に対してファイルをドロップさせファイルパスを表示する。
といういたってシンプルなものを作ろうとしたが、ReactiveProperty で作れない…なぜだ!
って事でとりあえず動かないソース:(一部抜粋)
MainPage.xaml:
<UserControl なんかいろいろ
xmlns:prism="http://prismlibrary.com/"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:rpi="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<TextBox Text="{Binding FilePath.Value}" AllowDrop="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewDragOver">
<rpi:EventToReactiveCommand Command="{Binding PreviewDragOver}" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDragLeave">
<rpi:EventToReactiveCommand Command="{Binding PreviewDragLeave}" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDrop">
<rpi:EventToReactiveCommand Command="{Binding PreviewDrop}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
</Grid>
</UserControl>
MainPageViewModel:
public class MainPageViewModel : RegionViewModelBase, IDisposable, IDestructible
{
public ReactiveProperty<string> FilePath { get; set; }
public ReactiveCommand<DragEventArgs> PreviewDragOver { get; set; }
public ReactiveCommand<DragEventArgs> PreviewDragLeave { get; set; }
public ReactiveCommand<DragEventArgs> PreviewDropFile { get; set; }
public MainPageViewModel()
{
FilePath = new ReactiveProperty<string>();
PreviewDragOver = new ReactiveCommand<DragEventArgs>().WithSubscribe(DoPreviewDragOver);
PreviewDragLeave = new ReactiveCommand<DragEventArgs>().WithSubscribe(DoPreviewDragLeave);
PreviewDrop = new ReactiveCommand<DragEventArgs>().WithSubscribe(DoDropFile);
}
private void DoPreviewDragOver(DragEventArgs e)
{
e.Handled = true;
e.Effects = DragDropEffects.Copy;
}
private void DoPreviewDragLeave(DragEventArgs e)
{
e.Effects = DragDropEffects.None;
e.Handled = false;
}
private void DoDropFile(DragEventArgs e)
{
// ここに処理が来ない
}
}何がダメか:
1.DoPreviewDragOver メソッドに処理が来るが、Handled と Effects に値を設定しても、反映されていないっぽい。
⇒ 結果、画面のマウスマークは禁止マークから変更されない。
2.上記より、DoDropFile メソッドが呼び出されない。
ちなみに「コードビハインド(*.xaml.cs) でイベントを記載した所、同じ処理でも正常に動作する」てな感じです。
で、悩むこと数日… たまたま Reactiveで有名(本家)な かずきさん のページをぼーっと眺めていると
ここ:https://blog.okazuki.jp/entry/2019/04/19/172010
Reactive でのイベント発火方法と、Prismのイベント発火方法が記載されているではないですか…
まさかね…と思いつつ下記を変更(XAML)
修正前:(Reactive で送信する方法)
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewDragOver">
<rpi:EventToReactiveCommand Command="{Binding PreviewDragOver}" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDragLeave">
<rpi:EventToReactiveCommand Command="{Binding PreviewDragLeave}" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDrop">
<rpi:EventToReactiveCommand Command="{Binding PreviewDrop}" />
</i:EventTrigger>
</i:Interaction.Triggers>
修正後:(Prismで送る方法)
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewDragOver">
<prism:InvokeCommandAction Command="{Binding PreviewDragOver}"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDragLeave">
<prism:InvokeCommandAction Command="{Binding PreviewDragLeave}"/>
</i:EventTrigger>
<i:EventTrigger EventName="PreviewDrop">
<rpi:EventToReactiveCommand Command="{Binding PreviewDrop}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
変更箇所:
<rpi:EventToReactiveCommand Command="{Binding PreviewDragOver}" />
<rpi:EventToReactiveCommand Command="{Binding PreviewDragLeave}" />
↓
<prism:InvokeCommandAction Command="{Binding PreviewDragOver}"/>
<prism:InvokeCommandAction Command="{Binding PreviewDragLeave}"/>
に変更しました。
<rpi:EventToReactiveCommand Command="{Binding PreviewDrop}"/> はそのままです。
こっちは引数のEventArgs を参照しかしないので不要と判断です。
と言う訳で、Prism 側でイベントを発火すると、正しく処理できました!
EventArgs のインスタンスが直接渡されてるのかなぁ…? しかし罠だよなぁ…
しかしずいぶん昔に、Reactive系のイベント引数は「実物を渡してない」ってどこかで読んだ気がするが、気のせいだったのか探し出せない。
解決策も書いてあった気がしたんだけどなぁ…引数か何かで変更できなかったっけか…?
気のせいだったかなぁ…?
ま、これでコードビハインド無しでD&Dが出来たのでOK!!!
Prism を利用しない場合はどうするのか知りませんが、コードビハインドしかないのでは?
ここの方も同じ原因では?と思いながら、自分よりもわかりやすいと思うので拝借します。
https://maywork.net/computer/wpf-reactcommand-dd/
.net 6
Prism.Dryloc:8.1.97
Prism.Wpf:8.1.97
ReactiveProperty:9.5.0
ReactiveProperty.WPF:9.5.0
/**********************************************************************************本記事はGooブログから作成者本人が移行しました。**********************************************************************************/
コメント
コメントを投稿