Мы можем использовать класс System.IO.DriveInfo для извлечения всех дисков в системе и искать приводы, где DriveType является съемным. Кроме того, съемный диск (обычно USB) должен быть готов, доступный как свойство IsReady.
Во-первых, мы определяем провайдера для извлечения съемных дисков:
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace TestPopWpfWindow
{
public static class UsbDriveListProvider
{
public static IEnumerable<DriveInfo> GetAllRemovableDrives()
{
var driveInfos = DriveInfo.GetDrives().AsEnumerable();
driveInfos = driveInfos.Where(drive => drive.DriveType == DriveType.Removable);
return driveInfos;
}
}
}
Давайте использовать шаблон MVVM и, таким образом, мы определим ViewModelbase класс, внедрение INotifyPropertyChanged.
using System.ComponentModel;
namespace TestPopWpfWindow
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Это также удобно иметь реализацию в ICommand:
using System;
using System.Windows.Input;
namespace TestPopWpfWindow
{
public class RelayCommand : ICommand
{
private Predicate<object> _canExecute;
private Action<object> _execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
_canExecute = canExecute;
_execute = execute;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_execute(parameter);
}
}
}
Мы также устанавливаем DataContext из MainWindow к экземпляру модели представления демонстрационной определенному впоследствии:
namespace TestPopWpfWindow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new UsbDriveInfoDemoViewModel();
}
}
}
Затем мы определяем модель представления и используем System.Manag ement.ManagementEventWatcher искать изменения в приводах, установленных в системе.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Management;
using System.Windows;
using System.Windows.Input;
namespace TestPopWpfWindow
{
public class UsbDriveInfoDemoViewModel : ViewModelBase, IDisposable
{
public UsbDriveInfoDemoViewModel()
{
DriveInfos = new List<DriveInfo>();
ReloadDriveInfos();
RegisterManagementEventWatching();
TargetUsbDrive = @"E:\";
AccessCommand = new RelayCommand(x => true, x => MessageBox.Show("Functionality executed."));
}
public int UsbDriveCount { get; set; }
private string _targetUsbDrive;
public string TargetUsbDrive
{
get { return _targetUsbDrive; }
set
{
if (_targetUsbDrive != value)
{
_targetUsbDrive = value;
RaisePropertyChanged("TargetUsbDrive");
RaisePropertyChanged("DriveInfo");
}
}
}
public ICommand AccessCommand { get; set; }
private void ReloadDriveInfos()
{
var usbDrives = UsbDriveListProvider.GetAllRemovableDrives();
Application.Current.Dispatcher.Invoke(() =>
{
DriveInfos.Clear();
foreach (var usbDrive in usbDrives)
{
DriveInfos.Add(usbDrive);
}
UsbDriveCount = DriveInfos.Count;
RaisePropertyChanged("UsbDriveCount");
RaisePropertyChanged("DriveInfos");
});
}
public List<DriveInfo> DriveInfos { get; set; }
private ManagementEventWatcher _watcher;
private void RegisterManagementEventWatching()
{
_watcher = new ManagementEventWatcher();
var query = new WqlEventQuery("SELECT * FROM Win32_VolumeChangeEvent");
_watcher.EventArrived += watcher_EventArrived;
_watcher.Query = query;
_watcher.Start();
}
private void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
Debug.WriteLine(e.NewEvent);
ReloadDriveInfos();
}
public void Dispose()
{
if (_watcher != null)
{
_watcher.Stop();
_watcher.EventArrived -= watcher_EventArrived;
}
}
}
}
Мы также определить WPF мультиконвертера следующий, чтобы активировать кнопку:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Windows.Data;
namespace TestPopWpfWindow
{
public class UsbDriveAvailableEnablerConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Count() != 2)
return false;
var driveInfos = values[1] as List<DriveInfo>;
var targetDrive = values[0] as string;
if (driveInfos == null || !driveInfos.Any() || string.IsNullOrEmpty(targetDrive))
return false;
return driveInfos.Any(d => d.IsReady && d.Name == targetDrive);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
И мы определяем GUI, чтобы проверить этот код:
<Window x:Class="TestPopWpfWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestPopWpfWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="usbLabel" TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding IsReady}" Value="False">
<Setter Property="Background" Value="Gray"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsReady}" Value="True">
<Setter Property="Background" Value="Green"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<local:UsbDriveAvailableEnablerConverter x:Key="usbDriveAvailableEnablerConverter"></local:UsbDriveAvailableEnablerConverter>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical">
<TextBlock Text="USB Drive-detector" FontWeight="DemiBold" HorizontalAlignment="Center" FontSize="14" Margin="2"></TextBlock>
<TextBlock Text="Removable drives on the system" FontWeight="Normal" HorizontalAlignment="Center" Margin="2"></TextBlock>
<TextBlock Text="Drives detected:" FontWeight="Normal" HorizontalAlignment="Center" Margin="2"></TextBlock>
<TextBlock Text="{Binding UsbDriveCount, UpdateSourceTrigger=PropertyChanged}" FontWeight="Normal" HorizontalAlignment="Center" Margin="2"></TextBlock>
<ItemsControl Grid.Row="0" ItemsSource="{Binding DriveInfos, UpdateSourceTrigger=PropertyChanged}"
Width="100" BorderBrush="Black" BorderThickness="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Label Style="{StaticResource usbLabel}" Width="32" Height="32" FontSize="18" Foreground="White" Content="{Binding Name}">
</Label>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<Button Grid.Row="1" Height="24" Width="130" VerticalAlignment="Top" Margin="10" Content="Access functionality" Command="{Binding AccessCommand}">
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource usbDriveAvailableEnablerConverter}">
<MultiBinding.Bindings>
<Binding Path="TargetUsbDrive"></Binding>
<Binding Path="DriveInfos"></Binding>
</MultiBinding.Bindings>
</MultiBinding>
</Button.IsEnabled>
</Button>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Margin="2" Text="Target this USB-drive:"></TextBlock>
<TextBox Margin="2" Text="{Binding TargetUsbDrive, UpdateSourceTrigger=LostFocus}" Width="100"></TextBox>
</StackPanel>
</Grid>
</Window>
Я теперь при условии, что Решение Visual Studio 2013 с кодом выше можно скачать здесь:
https://onedrive.live.com/redir?resid=8EF5059044F781FC!40934&authkey=!AAkLBdsXTlMMTy4&ithint=file%2czip
Попробуйте взглянуть на это сообщение http://stackoverflow.com/questions/3685615/usb-device-connected – bgura