USBデバイスの抜き差しを検知する
やりたいこと
USBデバイスが抜き差しされたタイミングで、ViewModelのコマンドを実行する。
実装
USB抜き差し時にコマンドを実行するビヘイビアを作成する。
ビヘイビア
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
namespace Sample {
public class DeviceChangeBehavior {
private static readonly uint WM_DEVICECHANGE = 0x0219;
public static DependencyProperty CommandProperty
= DependencyProperty.RegisterAttached(
"Command",
typeof(ICommand),
typeof(DeviceChangeBehavior),
new PropertyMetadata(Command_PropertyChanged)
);
public static void SetCommand(FrameworkElement element, ICommand value)
=> element.SetValue(CommandProperty, value);
public static ICommand GetCommand(FrameworkElement element)
=> (ICommand)element.GetValue(CommandProperty);
private static Dictionary<FrameworkElement, ICommand> _commands
= new Dictionary<FrameworkElement, ICommand>();
private static void Command_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var element = d as FrameworkElement;
if (element == null) return;
if (e.NewValue != null) {
element.Loaded += FrameworkElement_Loaded;
_commands.Add(control, e.NewValue as ICommand);
} else {
element.Loaded -= FrameworkElement_Loaded;
var handle = ((HwndSource)HwndSource.FromVisual(element)).Handle;
var source = HwndSource.FromHwnd(handle);
source.RemoveHook(WndProc);
_commands.Remove(element);
}
}
private static void FrameworkElement_Loaded(object sender, RoutedEventArgs e) {
var element = sender as FrameworkElement;
if (element == null) return;
//ロード完了後でないとハンドラを登録できない
var handle = ((HwndSource)HwndSource.FromVisual(element)).Handle;
var source = HwndSource.FromHwnd(handle);
source.AddHook(WndProc);
}
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
if (msg != WM_DEVICECHANGE)
return IntPtr.Zero;
_commands
.Select(x => new { ((HwndSource)HwndSource.FromVisual(x.Key))?.Handle, Command = x.Value })
.Where(x => x.Handle == hwnd && x.Command.CanExecute(null))
.ForEach(x => x.Command.Execute(null));
return IntPtr.Zero;
}
}
}
使い方
XAML
<Window x:Class="Sample.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Sample"
local:DeviceChangeBehavior.Command="{Binding XXXCommand}"
Title="MainView" Height="300" Width="300">
<Grid>
<TextBox />
</Grid>
</Window>
XAML
<Window x:Class="Sample.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Sample"
local:DeviceChangeBehavior.Command="{Binding XXXCommand}"
Title="MainView" Height="300" Width="300">
<Grid>
<TextBox />
</Grid>
</Window>
Window以外にも指定できるが、ルート要素に指定するのが無難。
Author And Source
この問題について(USBデバイスの抜き差しを検知する), 我々は、より多くの情報をここで見つけました https://qiita.com/flasksrw/items/ff08dec754c33b651db0著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .