c# WPF实现Windows资源管理器(附源码)

    今天我来写一篇关于利用WPF来实现Windows的资源管理器功能,当然只是局部实现这个功能,因为在很多时候我们需要来实现对本机资源的管理,当然我们可以使用OpenFileDialog dialog = new OpenFileDialog()这个Microsoft.Win32命名空间下的这个类来实现一些资源查找和导入的功能,但是在很多时候我们可能需要更多的功能,并且希望能够集成到我们自己的项目中,但是我们这个时候就不得不自己来写一套来集成到我们的软件中去了,因为OpenFileDialog这个是无法作为一个UserControl加入到我们的项目中的,当然我们只是实现了其中的一部分功能,因为Windows的资源管理器也是一个重量级的应用,也是十分庞大和复杂的,这里只是通过这个Demo来加深对WPF的MVVM模式及软件基本功的巩固。

  在正式介绍整体框架之前,首先来看看整体的结构,从而对其有一个大概的了解。

  整个界面从大的方面来说主要包括三个方面:1 文件及文件夹显示区域、2 导航区域、3 路径显示区域,其实在整个界面中,2和3都是围绕1来进行操作的,三个区域之间的耦合性其实是非常高的,所以常规的做法就是三个部分分为三个UserControl,并且同时绑定到一个ViewModel中,这样整个层次也就比较清晰了,缺点是一个ViewModel中代码太多,职责非常大,所以在这个DEMO中尝试将三个部分分开,三个ViewModel来操作三个View里面的内容,整个实现下来其实也有一些不足之处,那就是容易将问题复杂化,很多在一个类中就能够完成的工作,最终要通过各种类与类之间的耦合来完成,所以通过这个DEMO希望自己能够多一些思考,从而在软件的设计中能够再多一些经验,能够把握好软件粒度的问题,下面就软件的具体内容来深入分析一下。

第一部分:FileList

  这个部分是整个文件和文件夹的显示部分,再三权衡下,决定采用自定义DataGrid的方式来展现整个部分。

<UserControl x:Class="FileSelectorDemo.Views.FileList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:converter="clr-namespace:FileSelectorDemo.Converters"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:defines="clr-namespace:FileSelectorDemo.Defines"
             xmlns:local="clr-namespace:FileSelectorDemo.Views"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <converter:CountToVisibilityConverter x:Key="CountToVisibilityConverter"></converter:CountToVisibilityConverter>
        <converter:TypeToVisibleConverter x:Key="TypeToVisibleConverter"></converter:TypeToVisibleConverter>
        <converter:TypeToCollapsedConverter x:Key="TypeToCollapsedConverter"></converter:TypeToCollapsedConverter>
        <converter:CollectionSelectedCountConverter x:Key="CollectionSelectedCountConverter"></converter:CollectionSelectedCountConverter>      
    </UserControl.Resources>
    <Grid>     
        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
            <Grid>
                <StackPanel Orientation="Vertical">
                    <DataGrid x:Name="fileList" Style="{StaticResource DefaultDataGrid}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" defines:MouseDoubleClick.Command="{Binding OpenCurrentDirectory}"
                              defines:MouseDoubleClick.CommandParameter="{Binding SelectedItem,RelativeSource={RelativeSource Self}}"  IsReadOnly="True"
                              defines:MouseLeftButtonUpClick.Command="{Binding SelectCurrentFileListItem}" ItemsSource="{Binding CurrentFileList}"  CanUserAddRows="False"  AutoGenerateColumns="False" GridLinesVisibility="None">
                        <DataGrid.Columns>
                            <DataGridTemplateColumn  MinWidth="60">
                                <DataGridTemplateColumn.Header>
                                    <CheckBox Content="全选" Margin="2" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding DataContext.IsStateCheckAll,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"></CheckBox>
                                </DataGridTemplateColumn.Header>
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
                                            <TextBlock Text="不可选" FontSize="12" Foreground="Black" Visibility="{Binding CurrentType,Converter={StaticResource TypeToCollapsedConverter}}" HorizontalAlignment="Left" VerticalAlignment="Center" ></TextBlock>
                                            <CheckBox IsChecked="{Binding IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" IsThreeState="False" IsHitTestVisible="False" Visibility="{Binding CurrentType,Converter={StaticResource TypeToVisibleConverter}}"  HorizontalAlignment="Left" VerticalAlignment="Center" ToolTip="点击选中当前对象"></CheckBox>
                                        </Grid>
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>
                            <DataGridTemplateColumn Header="名称" >
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
                                            <Image Source="{Binding Icon}" Margin="2"  HorizontalAlignment="Center" VerticalAlignment="Center"></Image>
                                            <TextBlock Text="{Binding Name}" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
                                        </StackPanel>
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>
                            <DataGridTextColumn Header="修改日期"   Binding="{Binding CreateTime}"/>
                            <DataGridTextColumn Header="类型"   Binding="{Binding CurrentType}"/>
                            <DataGridTextColumn Header="大小"  Binding="{Binding Size}"/>
                        </DataGrid.Columns>
                    </DataGrid>
                    <TextBlock Margin="2 5" HorizontalAlignment="Left" VerticalAlignment="Center" >
                        <Run>总共 </Run>
                        <Run Text="{Binding CurrentFileList.Count,Mode=OneWay}"></Run>
                        <Run> 个项目</Run>
                        <Run>(已选中 </Run>
                        <Run Text="{Binding CurrentFileList,Converter={StaticResource CollectionSelectedCountConverter},Mode=OneWay}"></Run>
                        <Run> 个项目)</Run>
                    </TextBlock>
                </StackPanel>
                <TextBlock Text="该文件为空"  Visibility="{Binding CurrentFileList.Count,Converter={StaticResource CountToVisibilityConverter}}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
            </Grid>
        </ScrollViewer>         
    </Grid>
</UserControl>

  这里都是一些常规的定义,这里就不再赘述,DataGrid样式是引用Themes文件夹下面的CustomDataGrid的样式,这里面也包括自定义的ScrollViewer样式和ScrollBar的样式,读者也可以进行思考,另外需要注意设置下面的几个属性。

  1  IsReadOnly="True"这个属性能够保证在鼠标点击时候,不再显示内部的TextBox,从而使使用者不能够随意进行编辑。

  2  GridLinesVisibility="None" 这个能够使整个DataGrid不再显示分割线,从而使其样式更加接近Windows的原生样式。

  3  CanUserAddRows="False" 这个属性也非常重要,不然在整个显示区域的下面会多出一行,当用户点击它的时候会增加行。

  4  AutoGenerateColumns="False"这个就比较熟悉了,一般不让其自动增加列。

  5   SelectionUnit=“FullRow” 表示鼠标点击时选择的单位是整行,而不是其中的单元格或者其他,关于其它的几个枚举值,读者也可查阅相关了解。

  6   SelectionMode=“Extended”允许多选,当按下鼠标的Ctrl键进行点击的时候能够选中多个对象。

  7   最后一个就是关于设置DataGrid的虚拟化容器了,具体设置方法是:

 <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"></Setter>
 <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" />

  WPF中的VirtualizingStackPanel.VirtualizationMode 附加属性指定 ItemsControl 中的面板如何虚拟化其子项。默认情况下,VirtualizingStackPanel 将为每个可见项创建一个项容器,并在不再需要时(比如当项滚动到视图之外时)丢弃该容器。当 ItemsControl 包含多个项时,创建和废弃项容器的过程可能会对性能产生负面影响。如果 VirtualizingStackPanel.VirtualizationMode 设置为 Recycling,VirtualizingStackPanel 将重用项容器,而不是每次都创建新的项容器,这个是摘录自MSDN的相关资料,由于我们加载的DataGrid的项不是很多,如果足够多的情况下,效果可能会更加明显,关于更多的“虚拟化”技术可以参考更多的资料。

  这里我们需要重点关注的是当我们双击DataGridRow时会打开对应的子文件夹,同时单击时会选中当前的DataGridRow,这里关于事件的绑定我们使用的不是System.Windows.Interactivity这种方式来绑定事件的,这里我们通过自定义一个附加属性来实现的,这里以鼠标左键双击为例来进行说明。

  这里需要进行说明的就是在OnMouseDoubleClick中,我们通过当前鼠标的点击的Point来查找最终的DataGridRow 然后触发绑定的Command事件,在前台View中,我们只需要通过绑定到对应的ICommand即可。

public class MouseDoubleClick
{
    public static DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached("Command",
        typeof(ICommand),
        typeof(MouseDoubleClick),
        new UIPropertyMetadata(CommandChanged));
 
    public static DependencyProperty CommandParameterProperty =
        DependencyProperty.RegisterAttached("CommandParameter",
                                            typeof(object),
                                            typeof(MouseDoubleClick),
                                            new UIPropertyMetadata(null));
 
    public static void SetCommand(DependencyObject target, ICommand value)
    {
        target.SetValue(CommandProperty, value);
    }
 
    public static void SetCommandParameter(DependencyObject target, object value)
    {
        target.SetValue(CommandParameterProperty, value);
    }
    public static object GetCommandParameter(DependencyObject target)
    {
        return target.GetValue(CommandParameterProperty);
    }
 
    private static void CommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        Control control = target as Control;
        if (control != null)
        {
            if ((e.NewValue != null) && (e.OldValue == null))
            {
                control.MouseDoubleClick += OnMouseDoubleClick;
            }
            else if ((e.NewValue == null) && (e.OldValue != null))
            {
                control.MouseDoubleClick -= OnMouseDoubleClick;
            }
        }
    }
 
    private static void OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        DataGrid datagrid = sender as DataGrid;
        Point point = e.GetPosition(datagrid);
        IInputElement obj = datagrid.InputHitTest(point);
        DependencyObject target = obj as DependencyObject;
 
        while (target != null)
        {
            if (target is DataGridRow)
            {
                ICommand command = (ICommand)datagrid.GetValue(CommandProperty);
                object commandParameter = datagrid.GetValue(CommandParameterProperty);
                if (null != commandParameter)
                {
                    command.Execute(commandParameter);
                }
                break;
            }
            target = VisualTreeHelper.GetParent(target);
        }
    }
}  
defines:MouseDoubleClick.Command="{Binding OpenCurrentDirectory}"  defines:MouseDoubleClick.CommandParameter="{Binding SelectedItem,RelativeSource={RelativeSource Self}}"

  其中我们需要定义命名空间defines,这种方法为我们绑定View层中的各种事件提供能了一种新的方式,这个是我们需要不断去总结和分析的地方。

  第二部分:Navigation

这一部分是我们的导航栏的部分,通过向前、向后、向上等快捷操作,我们能够快速切换文件夹,从而使切换路径变得更加容易,这一部分就是需要着重说一下最近浏览项目这个功能,它能够保存用户最近浏览的10个目录(开发者自定义),从而方便用户迅速切换不同的路径,这个是通过ToggleButton和Popup这一对经典的组合来实现的,具体实现请参考源代码。这一部分重点来说一下当鼠标移动到不同的位置时,能够变换绑定的图标是向前还是向后抑或选中状态,这个其实是通过绑定每一个Model的一个CurrentDirection来实现的,这里需要重点掌握DataTrigger的使用方法。

<Popup Placement="Bottom" PlacementTarget="{Binding ElementName=NavigationPanel}" StaysOpen="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
               IsOpen="{Binding IsChecked,ElementName=History,Mode=OneWay}" PopupAnimation="Slide">
            <ItemsControl Background="#f5f5f5" BorderBrush="Gray" BorderThickness="1" Padding="0"
                          ItemsSource="{Binding AttachedDataContext.DirectoryHistory,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}">
                <ItemsControl.Template>
                    <ControlTemplate TargetType="{x:Type ItemsControl}">
                        <Border x:Name="outer" Padding="0 2" Background="#f5f5f5">
                            <StackPanel Orientation="Vertical" IsItemsHost="True"></StackPanel>
                        </Border>                       
                    </ControlTemplate>
                </ItemsControl.Template>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button x:Name="radioButton" Command="{Binding AttachedDataContext.SwitchDirectory,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}"
                                CommandParameter="{Binding}">
                            <Button.Template>
                                <ControlTemplate TargetType="{x:Type Button}">
                                    <Border x:Name="bg" Padding="0" Background="#f5f5f5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
                                            <Path x:Name="path" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" Stroke="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"  Width="24" Height="24"
                                                  Opacity="0" StrokeThickness="2"  StrokeLineJoin="Round"  SnapsToDevicePixels="False">                                               
                                            </Path>                                        
                                            <Image Source="{Binding Icon}" Width="24" Height="24" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center"></Image>
                                            <TextBlock Text="{Binding Name}" Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
                                        </StackPanel>
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <DataTrigger Binding="{Binding CurrentDirection}" Value="选中">
                                            <Setter Property="Opacity" Value="1" TargetName="path"></Setter>
                                            <Setter Property="Data" Value="M 2,10 L 8,14 18,6" TargetName="path"></Setter>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding CurrentDirection}" Value="向前">
                                            <Setter Property="Opacity" Value="0" TargetName="path"></Setter>
                                            <Setter Property="Data" Value="M8,6 L1,11 8,16 M0,11 L15,11" TargetName="path"></Setter>
                                        </DataTrigger>
                                        <DataTrigger Binding="{Binding CurrentDirection}" Value="向后">
                                            <Setter Property="Opacity" Value="0" TargetName="path"></Setter>
                                            <Setter Property="Data" Value="M8,6 L15,11 8,16 M0,11 L15,11" TargetName="path"></Setter>
                                        </DataTrigger>
                                        <Trigger Property="IsMouseOver" Value="true">
                                            <Setter Property="Background" Value="#91c9f7" TargetName="bg"></Setter>
                                            <Setter Property="Opacity" Value="1" TargetName="path"></Setter>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Button.Template> 
                        </Button>                                     
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Popup>

  第三部分:BreadCrumbView

   这个部分是用来显示当前文件夹路径,并进行快速切换准备的,这个部分是一个组合控件,主要是通过ItemsControl和ToggleButton和Popup来实现的,这个里面需要注意的是这里面绑定的命令和方法都是在FileList的ViewModel中定义的,这里为了最大程度的实现代码的重用。很多时候我们会发现通过这种方式我们需要能够随时访问到FileListViewModel中的内容,这个是整个DEMO中最重要的部分,所以如何才能够引用到FileListViewModel里面的内容呢?

public partial class BreadCrumbView : UserControl
    {
        public BreadCrumbView()
        {
            InitializeComponent();
            Loaded +=new RoutedEventHandler(BreadCrumbView_Loaded);
        }
 
        private void BreadCrumbView_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = new ViewModels.BreadCrumbViewModel(AttachedDataContext);
        }
 
        /// <summary>
        /// 当前FileList的DataContext对象
        /// </summary>
        public object AttachedDataContext
        {
            get { return (object)GetValue(AttachedDataContextProperty); }
            set { SetValue(AttachedDataContextProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AttachedDataContextProperty =
            DependencyProperty.Register("AttachedDataContext", typeof(object), typeof(BreadCrumbView), new PropertyMetadata(null));
    }

    通过定义一个AttachedDataContext对象,我们能够将FileListViewModel中定义的属性分散到各个ViewModel中,这样在一定程度上能够保证避免FileListViewModel中代码过多同时职责过重的问题,但是同时我们也发现了,如果彼此之间的耦合过大,采用这种方式会加重代码之间的复杂度,因为有时不得不通过Action或者事件等方式来进行ViewModel之间的交互和通讯,所以降到这里我们不得不说一些较大较复杂的项目中使用框架的重要性了,比如Prism亦或是Caliburn.Micro等框架能够使整个软甲架构看起来更加清楚和明白,这也是为了更好地增加软件的模块化和灵活性。

  通过这个DEMO的分析,我们需要在不断的实践中去总结这类型的经验,从而使整个软件显得更加合理,最终使自己能够真正地对软件的架构的思想有一个比较深入的了解。

最后需要整个Demo的请点击此处进行下载!

以上就是c# WPF实现Windows资源管理器(附源码)的详细内容,更多关于c# WPF实现Windows资源管理器的资料请关注我们其它相关文章!

(0)

相关推荐

  • c# WPF中System.Windows.Interactivity的使用

    背景 在我们进行WPF开发应用程序的时候不可避免的要使用到事件,很多时候没有严格按照MVVM模式进行开发的时候习惯直接在xaml中定义事件,然后再在对应的.cs文件中直接写事件的处理过程,这种处理方式写起来非常简单而且不用过多地处理考虑代码之间是否符合规范,但是我们在写代码的时候如果完全按照WPF规范的MVVM模式进行开发的时候就应该将相应的事件处理写在ViewModel层,这样整个代码才更加符合规范而且层次也更加清楚,更加符合MVVM规范. 常规用法 1 引入命名空间 通过在代码中引入Syst

  • C# WPF 建立无边框(标题栏)的登录窗口的示例

    前言:笔者最近用c#写WPF做了一个项目,此前未曾做过完整的WPF项目,算是一边学一边用,网上搜了不少资料,效率当然是不敢恭维的,有时会在一些很简单的问题上纠结很长时间,血与泪的教训可不少. 不过,正如电视剧某榜里的一句话:既然我活了下来,就不会白白活着!笔者怎么也算挣扎过了,有些经验与教训可以分享,趁着记忆深刻总结写下来.希望后来者少走弯路,提高工作效率.如果有写得不好的地方,希望读者能够指正,一起进步! --------------------------------- 今天先从登录窗口说起

  • C#中WPF依赖属性的正确学习方法

    前言 我在学习WPF的早期,对依赖属性理解一直都非常的不到位,其恶果就是,我每次在写依赖属性的时候,需要翻过去的代码来复制黏贴. 相信很多朋友有着和我相同的经历,所以这篇文章希望能帮助到那些刚刚开始学依赖属性的朋友. 那些[讨厌]的依赖属性的讲解文章 初学者肯定会面临一件事,就是百度,谷歌,或者MSDN来查看依赖属性的定义和使用,而这些文章虽然都写的很好,但,那是相对于已经学会使用依赖属性的朋友而言. 而对于初学者而言,说是误导都不过分. 比如,官网的这篇文章https://docs.micro

  • C# WPF 父控件通过使用可视化树找到子控件的示例代码

    在我们使用WPF设计前台界面时,经常会重写数据模板,或者把控件放到数据模板里.但是一旦将控件放到数据模板中,在后台就没有办法通过控件的名字来获取它了,更没办法对它进行操作(例如,隐藏,改变控件的某个值). 如果你是比我还白的小白,对我刚刚陈述的东西不清楚,接下来我简单说一下什么是把控件放在数据模板中,怎么样的情况没法后台通过名字来获取控件,如果读者对于数据模板这些事儿已经清楚了,或者只关心如何使用可视化树可以将这部分跳过哈. 先上代码介绍一下什么是数据模板以WPF中ListBox控件为例: <L

  • C#中WPF ListView绑定数据的实例详解

    C#中WPF ListView绑定数据的实例详解 WPF中ListView用来显示数据十分方便, 我们可以将它分成几个列,每一个列用来显示一条数据,但是又是在一方之中. 那么怎样实现这样的效果的呢,这就要用绑定了. 我们先来看一看他的xmal代码 <ListView Name="receiveList" Grid.Row="0"> <ListView.View> <GridView> <GridView.Columns>

  • c# WPF如何实现滚动显示的TextBlock

    在我们使用TextBlock进行数据显示时,经常会遇到这样一种情况就是TextBlock的文字内容太多,如果全部显示的话会占据大量的界面,这是我们就会只让其显示一部分,另外的一部分就让其随着时间的推移去滚动进行显示,但是WPF默认提供的TextBlock是不具备这种功能的,那么怎么去实现呢? 其实个人认为思路还是比较清楚的,就是自己定义一个UserControl,然后将WPF简单的元素进行组合,最终实现一个自定义控件,所以我们顺着这个思路就很容易去实现了,我们知道Canvas这个控件可以通过设置

  • C# WPF上位机实现和下位机TCP通讯的方法

    下位机使用北京大华程控电源DH1766-1,上位机使用WPF.实现了电压电流实时采集,曲线显示.上午在公司调试成功,手头没有程控电源,使用TCP服务端模拟.昨天写的TCP服务端正好排上用场. 界面如下: 服务端 服务端实在上篇基础上实现的.需要做如下更改: while (true) { try { byte[] bufferDate = new byte[1024]; int realLen = pSocket.Receive(bufferDate); if (realLen <= 0) { t

  • c# WPF中如何自定义MarkupExtension

    在介绍这一篇文章之前,我们首先来回顾一下WPF中的一些基础的概念,首先当然是XAML了,XAML全称是Extensible Application Markup Language (可扩展应用程序标记语言),是专门用于WPF技术中的UI设计语言,通过使用XAML语言,我们能够快速设计软件界面,同时能够通过绑定这种机制能够很好地实现界面和实现逻辑之间的解耦,这个就是MVVM模式的核心了,那么今天我们介绍的MarkupExtension和XAML之间又有哪些的关系呢? Markup Extensio

  • 在C# WPF下自定义滚动条ScrollViewer样式的操作

    一.实现对ScrollViewer样式的自定义主要包括: 1.滚动条宽度设置 2.滚动条颜色 3.滚动条圆角 4.滚动条拉动时的效果mouseover 二.实现效果: 三.实现方法 1.创建资源字典( ResourceDictionary)文件 由于style代码比较多,之间在控件文件中加载style比较混乱,也不利于其它窗口复用,这里单独创建了ScrollViewDictionary.xaml文件代码如下: <ResourceDictionary xmlns="http://schema

  • C# WPF使用AForge类库操作USB摄像头拍照并保存

    项目中用到 USB 摄像头,需要根据情况进行图像抓拍,查了半天资料,比较多的是使用 WPFMediaKit 和 AForge . 但是由于项目要求不显示 USB 摄像头拍摄的画面,最终确定使用 AForge 解决. 下面用一个测试程序记录一下. 一.无预览拍照 首先建立一个 WPF 项目,我的就叫 AForgeTest,你们随意就好: 然后在 NuGet 包管理器中安装 AForge 库: 我只安装了图中打勾的几个库,这个根据自己项目需要安装就好. 不过用 USB 摄像头拍照必须安装: AFor

  • C# wpf Brush转Hex字符串的实例代码

    我就废话不多说了,大家还是直接看代码吧~ //from MaterialDesignDemo.Converters public class BrushToHexConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null) return null; string lowerH

  • C# WPF 通过委托实现多窗口间的传值的方法

    在使用WPF开发的时候就不免会遇到需要两个窗口间进行传值操作,当然多窗口间传值的方法有很多种,本文介绍的是使用委托实现多窗口间的传值. 在上代码之前呢,先简单介绍一下什么是C#中的委托(如果只想了解如何传值可以略过这部分)在网络上有很多对于委托的介绍和讲解,经过我的学习和总结加上了一点我自己的理解,我认为委托是一种类似于C语言的指针,但是它指向的是方法而不是变量.如果把委托看作一个变量,那么这个变量里存着的就是你目标方法的地址,调用委托约等于调用你的目标方法.(个人理解欢迎指正交流) 以下正文:

随机推荐