c\#WPF 구현 Windows 자원 관리자(소스 코드)

오늘 은 WPF 를 이용 하여 Windows 의 자원 관리자 기능 을 실현 하 는 것 에 관 한 글 을 쓰 겠 습 니 다.물론 부분 적 으로 만 이 기능 을 실현 할 수 있 습 니 다.왜냐하면 우 리 는 이 컴퓨터 자원 에 대한 관 리 를 실현 해 야 할 때 가 많 기 때 문 입 니 다.물론 우 리 는 OpenFileDialog dialog=new OpenFileDialog()라 는 Microsoft.Win 32 네 임 스페이스 의 이런 종 류 를 사용 하여 자원 검색 과 가 져 오 는 기능 을 실현 할 수 있 습 니 다.그러나 많은 경우 에 우 리 는 더 많은 기능 이 필요 하고 우리 자신의 프로젝트 에 통합 되 기 를 희망 할 수 있 습 니 다.그러나 우 리 는 이 럴 때 스스로 한 세트 를 써 서 우리 의 소프트웨어 에 통합 시 켜 야 합 니 다.OpenFileDialog 는 User Control 로 서 우리 의 프로젝트 에 가입 할 수 없 기 때 문 입 니 다.물론 우 리 는 그 중의 일부 기능 만 실 현 했 을 뿐 입 니 다.윈도 우즈 의 자원 관리자 도 중량급 의 응용 이기 때문에 매우 방대 하고 복잡 하 다.여 기 는 이 데 모 를 통 해 WPF 의 MVVM 모델 과 소프트웨어 기본 기 에 대한 공 고 를 강화 할 뿐이다.
전체적인 구 조 를 본 격 적 으로 소개 하기 전에 먼저 전체적인 구 조 를 살 펴 보고 이에 대해 대략적인 이 해 를 가진다.

전체 화면 은 큰 측면 에서 볼 때 주로 세 가지 측면 을 포함한다.하 나 는 파일 과 폴 더 디 스 플레이 구역,2 네 비게 이 션 구역,3 경로 디 스 플레이 구역 이다.사실은 전체 화면 에서 2 와 3 은 모두 1 을 중심 으로 조작 되 고 세 구역 간 의 결합 성 이 매우 높 기 때문에 일반적인 방법 은 세 부분 으로 나 뉘 어 세 개의 UserControl 이다.또한 하나의 ViewModel 에 연결 하면 전체적인 차원 도 뚜렷 해진 다.단점 은 하나의 ViewModel 에 코드 가 너무 많 고 직책 이 매우 크다 는 것 이다.그래서 이 DEMO 에서 세 부분 을 나 누고 세 개의 ViewModel 로 세 개의 View 안의 내용 을 조작 하려 고 시도 했다.전체적으로 실현 하면 부족 한 점도 있다.그것 은 바로 문 제 를 복잡 하 게 만 들 기 쉽다 는 것 이다.한 가지 유형 에서 완성 할 수 있 는 많은 일 들 이 최종 적 으로 각 종류 와 유형 간 의 결합 을 통 해 이 루어 져 야 한다.그래서 이 DEMO 를 통 해 자신 이 더 많은 사 고 를 하고 소프트웨어 의 디자인 에서 경험 을 많이 하고 소프트웨어 의 입도 문 제 를 잘 파악 할 수 있 기 를 바란다.다음은 소프트웨어 의 구체 적 인 내용 에 대해 깊이 분석 해 보 자.
      제1 부분: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  GridLines Visibility="None"는 전체 DataGrid 가 분할 선 을 표시 하지 않 고 Windows 의 네 이 티 브 스타일 에 더욱 가 깝 게 할 수 있 습 니 다.
  3  CanUser AddRows="False"라 는 속성 도 매우 중요 합 니 다.그렇지 않 으 면 전체 디 스 플레이 영역 아래 에 한 줄 이 더 나 오고 사용자 가 클릭 할 때 줄 이 추 가 됩 니 다.
  4  AutoGenerate Columns="False"는 비교적 익숙 하 며,일반적으로 열 을 자동 으로 추가 하지 못 하 게 합 니 다.
  5   Selection Unit="FullRow"는 마 우 스 를 클릭 할 때 선택 하 는 단 위 는 줄 전체 이지 그 중의 셀 이나 다른 것 이 아니 라 다른 몇 개의 매 거 진 값 에 대해 독자 도 관련 된 이 해 를 찾 아 볼 수 있다 는 것 을 나타 낸다.
  6   Selection Mode="Extended"는 여러 옵션 을 허용 합 니 다.마우스 의 Ctrl 키 를 눌 러 클릭 할 때 여러 대상 을 선택 할 수 있 습 니 다.
  7   마지막 으로 DataGrid 를 설정 하 는 가상 화 용기 입 니 다.구체 적 인 설정 방법 은:

 <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"></Setter>
 <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" />
WPF 의 Virtualizing StackPanel.VirtualizationMode 추가 속성 지정 ItemsControl 판 넬 의 하위 항목 을 어떻게 가상 화 합 니까?기본적으로 Virtualizing StackPanel 보 이 는 항목 마다 용 기 를 만 들 고 필요 하지 않 을 때(예 를 들 어 항목 이 보기 밖으로 굴 러 갈 때)용 기 를 버 립 니 다....해 야 한다 ItemsControl 여러 항목 을 포함 할 때,항목 용 기 를 만 들 고 폐기 하 는 과정 은 성능 에 부정적인 영향 을 미 칠 수 있 습 니 다.하면,만약,만약... VirtualizingStackPanel.VirtualizationMode 으로 설정 Recycling,VirtualizingStackPanel 매번 새로운 용 기 를 만 드 는 것 이 아니 라 항목 용 기 를 다시 사용 합 니 다.이것 은 MSDN 에서 발췌 한 관련 자료 입 니 다.우리 가 불 러 온 DataGrid 의 항목 이 많 지 않 기 때문에 충분 한 경우 효과 가 더욱 뚜렷 해 질 수 있 습 니 다.더 많은'가상 화'기술 에 대해 서 는 더 많은 자 료 를 참고 할 수 있 습 니 다.
여기 서 중요 한 것 은 DataGridRow 를 두 번 눌 렀 을 때 해당 하 는 하위 폴 더 를 열 고 눌 렀 을 때 현재 DataGridRow 를 선택 하 는 것 입 니 다.여기 서 이벤트 에 대한 바 인 딩 은 System.Windows.Interactivity 라 는 방식 으로 이 벤트 를 연결 하 는 것 이 아 닙 니 다.여기 서 우 리 는 추가 속성 을 사용자 정의 하여 이 루어 집 니 다.마우스 왼쪽 단 추 를 더 블 클릭 하 는 것 을 예 로 들 어 설명 한다.
여기 서 설명 해 야 할 것 은 OnMouse DoubleClick 에서 현재 마우스 가 클릭 한 Point 를 통 해 최종 DataGridRow 를 찾 은 다음 에 연 결 된 Command 이 벤트 를 터치 하 는 것 입 니 다.프론트 뷰 에서 저 희 는 해당 하 는 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 층 의 각종 사건 을 연결 하 는 데 새로운 방식 을 제공 할 수 있다.이것 은 우리 가 끊임없이 정리 하고 분석 해 야 할 부분 이다.
제2 부분:Navigation
      이 부분 은 내 비게 이 션 표시 줄 의 부분 입 니 다.앞으로,뒤로,위로 빠 른 동작 을 통 해 폴 더 를 빠르게 전환 하여 전환 경 로 를 쉽게 만 들 수 있 습 니 다.이 부분 은 최근 에 항목 을 탐색 하 는 기능 을 다시 말 해 야 합 니 다.사용자 가 최근 에 탐색 한 10 개의 디 렉 터 리(개발 자 사용자 정의)를 저장 할 수 있 습 니 다.따라서 사용자 가 서로 다른 경 로 를 신속하게 전환 하 는 데 편리 합 니 다.이것 은 ToggleButton 과 Popup 이라는 전형 적 인 조합 을 통 해 이 루어 진 것 입 니 다.구체 적 으로 실현 하려 면 소스 코드 를 참고 하 십시오.이 부분 에 서 는 마우스 가 서로 다른 위치 로 이동 할 때 바 인 딩 된 아이콘 이 앞으로 또는 뒤로 또는 선택 상 태 를 바 꿀 수 있 습 니 다.이것 은 모든 모델 을 연결 하 는 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
이 부분 은 현재 폴 더 경 로 를 표시 하고 빠 른 전환 준 비 를 하 는 데 사 용 됩 니 다.이 부분 은 하나의 조합 컨트롤 입 니 다.주로 Items Control 과 ToggleButton,Popup 을 통 해 이 루어 집 니 다.이 부분 에서 주의해 야 할 것 은 이 안에 연 결 된 명령 과 방법 은 모두 FileList 의 ViewModel 에서 정 의 된 것 입 니 다.코드 재 활용 을 최대한 실현 하기 위해 서 입 니 다.이러한 방식 을 통 해 우 리 는 수시로 FileListView Model 의 내용 을 방문 할 수 있어 야 한 다 는 것 을 알 게 될 때 가 많 습 니 다.이것 은 전체 DEMO 에서 가장 중요 한 부분 이기 때문에 어떻게 해야만 FileListView Model 의 내용 을 인용 할 수 있 습 니까?

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 의 분석 을 통 해 우 리 는 끊 임 없 는 실천 에서 이런 유형의 경험 을 정리 하여 전체 소프트웨어 를 더욱 합 리 적 으로 보이 고 최종 적 으로 소프트웨어 의 구조 사상 에 대해 깊이 있 게 이해 할 수 있 도록 해 야 한다.
       마지막 으로 전체 데모 가 필요 합 니 다여 기 를 클릭 하여 다운로드 하 세 요!
이상 은 c\#WPF 가 Windows 자원 관리자(원본 코드 첨부)를 실현 하 는 상세 한 내용 입 니 다.c\#WPF 가 Windows 자원 관리 자 를 실현 하 는 것 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기