寻找有关如何实现以下目标的一些建议:
我正在构建一个C#wpf应用程序,我想添加启动时应用程序的位置,检查特定的usb是否连接了任何一个usb端口 如果没有,申请人无法进行互动,直到说出来是否附上了?
关于如何做到这一点的任何想法?
答案 0 :(得分:3)
我们可以使用类 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 。
使用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);
}
}
}
我们还将MainWindow的 DataContext 设置为之后定义的演示视图模型的实例:
namespace TestPopWpfWindow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new UsbDriveInfoDemoViewModel();
}
}
}
然后我们定义视图模型本身并使用 System.Management.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解决方案,上面的代码可在此处下载:
答案 1 :(得分:0)
这是一篇解释如何获取所有当前连接的USB设备列表的帖子。