Pārlūkot izejas kodu

页面编辑-补充插入文件Undo,Redo

ZhouJieSheng 2 gadi atpakaļ
vecāks
revīzija
817fe715b1

+ 2 - 3
PDF Office/CustomControl/ToastControl.xaml

@@ -12,14 +12,13 @@
     d:DesignWidth="800"
     Background="Transparent"
     IsVisibleChanged="Toast_IsVisibleChanged"
-    Visibility="Collapsed"
+    Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ToastControl}, Path=Visibility}"
     mc:Ignorable="d">
     <Border
         Name="tipBorder"
         HorizontalAlignment="Center"
         Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ToastControl}, Path=Background}"
-        CornerRadius="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ToastControl}, Path=CornerRadius}"
-        Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ToastControl}, Path=Visibility}">
+        CornerRadius="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ToastControl}, Path=CornerRadius}">
         <TextBlock
             Name="txtTip"
             Padding="6,2,6,2"

+ 2 - 1
PDF Office/CustomControl/ToastControl.xaml.cs

@@ -83,6 +83,7 @@ namespace PDF_Office.CustomControl
         private void DoubleAnimation_Completed(object sender, EventArgs e)
         {
             this.Visibility = Visibility.Collapsed;
+            this.Opacity = 1;
         }
 
         private void Toast_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
@@ -95,7 +96,7 @@ namespace PDF_Office.CustomControl
                 doubleAnimation.To = 0;
                 doubleAnimation.BeginTime = BeginTime;
                 doubleAnimation.Duration = Duration;
-                this.BeginAnimation(UserControl.OpacityProperty,doubleAnimation);
+                this.BeginAnimation(UserControl.OpacityProperty, doubleAnimation);
             }
         }
     }

+ 14 - 1
PDF Office/DataConvert/FileToImageSourceConvert.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Globalization;
+using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -18,7 +19,19 @@ namespace PDF_Office.DataConvert
         {
             if(!string.IsNullOrEmpty((string)value)&&System.IO.File.Exists((string)value))
             {
-                return new BitmapImage(new Uri((string)value, UriKind.Relative));
+                //采用数组的形式读取,避免因bitmap占用,导致图片无法引用的问题
+                // Read byte[] from png file
+                BinaryReader binReader = new BinaryReader(File.Open((string)value, FileMode.Open));
+                FileInfo fileInfo = new FileInfo((string)value);
+                byte[] bytes = binReader.ReadBytes((int)fileInfo.Length);
+                binReader.Close();
+
+                // Init bitmap
+                BitmapImage bitmap = new BitmapImage();
+                bitmap.BeginInit();
+                bitmap.StreamSource = new MemoryStream(bytes);
+                bitmap.EndInit();
+                return bitmap;
             }
             return null;
         }

+ 42 - 1
PDF Office/Helper/CommonHelper.cs

@@ -1,8 +1,10 @@
-using System;
+using PDF_Office.Model.PageEdit;
+using System;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
+using System.Reflection;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
@@ -18,6 +20,8 @@ namespace PDF_Office.Helper
     /// 5.ShowFileBrowser 显示系统文件浏览器,可以根据传入的路径参数,自动选中对应的文件
     /// 6.CreateFilePath 检查对应路径是否有重名,有重名的情况追加尾号
     /// 7.CreateFolder 检查对应文件夹是否有重名,有重名的情况追加尾号
+    /// 8.GetUnitsFromPageSize 将PDF页面宽高转换成对应的单位
+    /// 9.GetDpi() 返回当前设备DPI
     /// </summary>
     public static class CommonHelper
     {
@@ -277,5 +281,42 @@ namespace PDF_Office.Helper
             info.Create();
             return folder;
         }
+
+        /// <summary>
+        /// 将Document 返回的PageSize 转换成对应单位
+        /// </summary>
+        /// <param name="size"></param>
+        /// <param name="unit"></param>
+        /// <returns></returns>
+        public static double GetUnitsFromPageSize(double size,PageItemUnits unit = PageItemUnits.MM)
+        {
+            double sizeWithUnit = 0;
+            switch (unit)
+            {
+                case PageItemUnits.MM:
+                    sizeWithUnit = (size * 96 / 72.0) / GetDpi() * 25.4;
+                    break;
+                case PageItemUnits.CM:
+                    sizeWithUnit = (size * 96 / 72.0) / GetDpi() * 25.4/10.0;
+                    break;
+                case PageItemUnits.IN:
+                    sizeWithUnit = (size * 96 / 72.0) / GetDpi();
+                    break;
+                default:
+                    break;
+            }
+            return sizeWithUnit;
+        }
+
+        /// <summary>
+        /// 返回设备DPI
+        /// </summary>
+        /// <returns></returns>
+        public static double GetDpi()
+        {
+            BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.NonPublic;
+            PropertyInfo property = typeof(SystemParameters).GetProperty("Dpi", bindingAttr);
+            return (int)property.GetValue(null, null);
+        }
     }
 }

+ 75 - 0
PDF Office/Model/PageEdit/PageEditHistory.cs

@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace PDF_Office.Model.PageEdit
+{
+    public class PageEditHistory
+    {
+        /// <summary>
+        /// 操作类型
+        /// </summary>
+        public ActionType Type { get; set; }
+
+        /// <summary>
+        /// 原位置-新位置集合  用于倒序、旋转、拖拽排序
+        /// </summary>
+        public Dictionary<int, int> SourceTargetValue { get; set; }
+
+        /// <summary>
+        /// 插入位置
+        /// </summary>
+        public int InsertIndex { get; set; }
+
+        /// <summary>
+        ///插入文件的文件路径
+        /// </summary>
+        public string InsertFilePath { get; set; }
+
+        /// <summary>
+        /// 插入文件的密码
+        /// </summary>
+        public string InsertFilePassWord { get; set; }
+
+        /// <summary>
+        /// 插入文档的页面总数
+        /// </summary>
+        public int InsertPageCount { get; set; }
+
+        /// <summary>
+        /// 插入的页面尺寸大小
+        /// </summary>
+        public Size PageSize { get; set; }
+    }
+
+    /// <summary>
+    /// 操作类型
+    /// </summary>
+    public enum ActionType
+    {
+        /// <summary>
+        /// 页面右旋转
+        /// </summary>
+        RightRotate,
+        /// <summary>
+        /// 页面左旋转
+        /// </summary>
+        LeftRotate,
+        /// <summary>
+        /// 从文件插入
+        /// </summary>
+        InsertFromFile,
+        /// <summary>
+        /// 插入自定义页面
+        /// </summary>
+        InsertCustomPages,
+        /// <summary>
+        /// 拖拽排序
+        /// </summary>
+        DragSort,
+
+    }
+}

+ 1 - 0
PDF Office/Model/PageEdit/PageEditItem.cs

@@ -100,6 +100,7 @@ namespace PDF_Office.Model.PageEdit
         private bool selected = false; 
         /// <summary>
         /// 是否选中
+        /// 用于获取项的选中状态
         /// </summary>
         public bool Selected
         {

+ 18 - 0
PDF Office/Model/PageEdit/PageItemUnits.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace PDF_Office.Model.PageEdit
+{
+    /// <summary>
+    /// 页面编辑 页面宽高单位 mm cm in
+    /// </summary>
+    public enum PageItemUnits
+    {
+       MM,
+       CM,
+       IN
+    }
+}

+ 11 - 9
PDF Office/PDF Office.csproj

@@ -281,7 +281,9 @@
     <Compile Include="Model\PageEdit\CustomInsertModel.cs" />
     <Compile Include="Model\PageEdit\CustomPageItem.cs" />
     <Compile Include="Model\PageEdit\ExtractModel.cs" />
+    <Compile Include="Model\PageEdit\PageEditHistory.cs" />
     <Compile Include="Model\PageEdit\PageEditItem.cs" />
+    <Compile Include="Model\PageEdit\PageItemUnits.cs" />
     <Compile Include="Model\ParameterNames.cs" />
     <Compile Include="Model\PDFTool\ToolItem.cs" />
     <Compile Include="Model\PropertyPanel\AnnotPanel\FontStyleItem.cs" />
@@ -1236,15 +1238,6 @@
     <Resource Include="Resources\HomeIcon\PDFTools\security.png" />
     <Resource Include="Resources\HomeIcon\PDFTools\split.png" />
     <Resource Include="Resources\HomeIcon\PDFTools\watermark.png" />
-    <Resource Include="Resources\PageEdit\GridLine.png">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Resource>
-    <Resource Include="Resources\PageEdit\HorizontalLine.png">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Resource>
-    <Resource Include="Resources\PageEdit\Staff.png">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Resource>
     <Resource Include="Resources\StampIcons\Accepted.png" />
     <Resource Include="Resources\StampIcons\Approved.png" />
     <Resource Include="Resources\StampIcons\Completed.png" />
@@ -1267,6 +1260,15 @@
     <Resource Include="Resources\StampIcons\SignHere.png" />
     <Resource Include="Resources\StampIcons\Void.png" />
     <Resource Include="Resources\StampIcons\Witness.png" />
+    <Content Include="Resources\PageEdit\GridLine.jpg">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="Resources\PageEdit\HorizontalLine.jpg">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="Resources\PageEdit\Staff.jpg">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
     <Content Include="source\AnalysisWord\Res\_rels\.rels">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>

PDF Office/Resources/PageEdit/GridLine.png → PDF Office/Resources/PageEdit/GridLine.jpg


PDF Office/Resources/PageEdit/HorizontalLine.png → PDF Office/Resources/PageEdit/HorizontalLine.jpg


PDF Office/Resources/PageEdit/Staff.png → PDF Office/Resources/PageEdit/Staff.jpg


+ 22 - 5
PDF Office/ViewModels/Dialog/PageEditDialogs/InsertDialogViewModel.cs

@@ -83,7 +83,18 @@ namespace PDF_Office.ViewModels.Dialog.PageEditDialogs
             }
         }
 
-
+        private int unitsSelectedIndex = 0;
+        /// <summary>
+        /// 单位下拉框的选中项索引
+        /// </summary>
+        public int UnitsSelectedIndex
+        {
+            get { return unitsSelectedIndex; }
+            set
+            {
+                SetProperty(ref unitsSelectedIndex, value);
+            }
+        }
 
 
         /// <summary>
@@ -96,6 +107,7 @@ namespace PDF_Office.ViewModels.Dialog.PageEditDialogs
         /// </summary>
         public List<string> Units { get; set; }
 
+
         public DelegateCommand CancelCommand { get; set; }
 
         public DelegateCommand InsertCommnad { get; set; }
@@ -120,7 +132,10 @@ namespace PDF_Office.ViewModels.Dialog.PageEditDialogs
         /// </summary>
         private  void InitUnits()
         {
-
+            Units = new List<string>();
+            Units.Add("mm");
+            Units.Add("cm");
+            Units.Add("in");
         }
 
         /// <summary>
@@ -130,9 +145,9 @@ namespace PDF_Office.ViewModels.Dialog.PageEditDialogs
         {
             Pages = new ObservableCollection<CustomPageItem>();
             Pages.Add(new CustomPageItem() {Name="空白页",FilePath = ""});
-            Pages.Add(new CustomPageItem() { Name="横线",FilePath= System.IO.Path.Combine(Environment.CurrentDirectory, @"Resources\PageEdit\HorizontalLine.png")});
-            Pages.Add(new CustomPageItem() { Name = "五线谱", FilePath = System.IO.Path.Combine(Environment.CurrentDirectory, @"Resources\PageEdit\Staff.png") });
-            Pages.Add(new CustomPageItem() { Name = "格子线", FilePath = System.IO.Path.Combine(Environment.CurrentDirectory, @"Resources\PageEdit\GridLine.png") });
+            Pages.Add(new CustomPageItem() { Name="横线",FilePath= System.IO.Path.Combine(Environment.CurrentDirectory, @"Resources\PageEdit\HorizontalLine.jpg")});
+            Pages.Add(new CustomPageItem() { Name = "五线谱", FilePath = System.IO.Path.Combine(Environment.CurrentDirectory, @"Resources\PageEdit\Staff.jpg") });
+            Pages.Add(new CustomPageItem() { Name = "格子线", FilePath = System.IO.Path.Combine(Environment.CurrentDirectory, @"Resources\PageEdit\GridLine.jpg") });
         }
 
         /// <summary>
@@ -195,6 +210,8 @@ namespace PDF_Office.ViewModels.Dialog.PageEditDialogs
             {
                 var size = parameters.GetValue<Size>("CurrentPageSize");
                 CurrentPageSize = $"({size.Width.ToString("F2")}mm*{size.Height.ToString("F2")}mm)";
+                CustomWidth = size.Width.ToString("F2");
+                CustomHeight = size.Height.ToString("F2");
                 Model.width = (int)size.Width;
                 Model.height = (int)size.Height;
             }

+ 406 - 138
PDF Office/ViewModels/PageEdit/PageEditContentViewModel.cs

@@ -50,14 +50,13 @@ namespace PDF_Office.ViewModels.PageEdit
         /// Undo操作记录栈
         /// 只有插入、移位、旋转,倒序需要记录
         /// </summary>
-        private Stack<PageEditItem> UndoStack = new Stack<PageEditItem>();
+        private Stack<PageEditHistory> UndoStack = new Stack<PageEditHistory>();
 
         /// <summary>
         /// Redo操作记录栈
         /// </summary>
 
-        private Stack<PageEditItem> RedoStack = new Stack<PageEditItem>();
-
+        private Stack<PageEditHistory> RedoStack = new Stack<PageEditHistory>();
 
         /// <summary>
         /// 项数据集合
@@ -219,7 +218,7 @@ namespace PDF_Office.ViewModels.PageEdit
         }
 
 
-        private string toastText;
+        private string toastText = "操作失败";
         /// <summary>
         /// Toast提示
         /// </summary>
@@ -245,6 +244,56 @@ namespace PDF_Office.ViewModels.PageEdit
                 SetProperty(ref isBOTAThumb, value);
             }
         }
+
+        private Visibility hasShowPageSize = Visibility.Collapsed;
+        /// <summary>
+        /// 是否显示页面尺寸
+        /// </summary>
+        public Visibility HasShowPageSize
+        {
+            get { return hasShowPageSize; }
+            set
+            {
+                SetProperty(ref hasShowPageSize, value);
+            }
+        }
+
+        private bool canUndo;
+
+        /// <summary>
+        /// 是否可以进行Undo操作
+        /// </summary>
+        public bool CanUndo
+        {
+            get { return canUndo; }
+            set
+            {
+                SetProperty(ref canUndo, value);
+                if (viewContentViewModel != null)
+                {
+                    viewContentViewModel.CanUndo = this.CanUndo;
+                }
+            }
+        }
+
+        private bool canRedo;
+        /// <summary>
+        /// 是否可以进行Redo操作
+        /// </summary>
+        public bool CanRedo
+        {
+            get { return canRedo; }
+            set
+            {
+                SetProperty(ref canRedo, value);
+                if(viewContentViewModel!=null)
+                {
+                    viewContentViewModel.CanRedo = this.CanRedo;
+                }
+ 
+            }
+        }
+
         #endregion
 
         #region 命令
@@ -309,6 +358,11 @@ namespace PDF_Office.ViewModels.PageEdit
         /// 缩小
         /// </summary>
         public DelegateCommand ZoomOutCommand { get; set; }
+
+        /// <summary>
+        /// 显示页面大小
+        /// </summary>
+        public DelegateCommand ShowPageSizeCommand { get; set; }
         #endregion
 
         public PageEditContentViewModel(IDialogService dialogService, IEventAggregator eventAggregator)
@@ -335,6 +389,7 @@ namespace PDF_Office.ViewModels.PageEdit
             ReverseCommand = new DelegateCommand(ReverseCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
             ZoomInCommand = new DelegateCommand(ZoomInCommandEvent, CanZoomIn).ObservesProperty(() => ZoomIndex);
             ZoomOutCommand = new DelegateCommand(ZoomOutCommandEvent, CanZoomOut).ObservesProperty(() => ZoomIndex);
+            ShowPageSizeCommand = new DelegateCommand(ShowPageSize);
 
             //订阅页面刷新事件
             eventAggregator.GetEvent<PageEditRefreshEvent>().Subscribe(OnPageEditRefreshEvent, e => e.Unicode == unicode);
@@ -428,22 +483,29 @@ namespace PDF_Office.ViewModels.PageEdit
             }
             IsLoading = Visibility.Visible;
             await Task.Delay(3);
+
+            PageEditHistory history = new PageEditHistory();
+            history.InsertIndex = insertIndex;
             if((string)type==ParameterNames.InsertType_Blank)
             {
+                history.Type = ActionType.InsertCustomPages;
+                history.InsertFilePath = "";
                 //插入空白页面
                 bool result;
                 if (insertIndex == 0)
                 {
                     result = PDFViewer.Document.InsertPage(insertIndex, PageEditItems[insertIndex].Size.Width, PageEditItems[insertIndex].Size.Height, null);
+                    history.PageSize = PageEditItems[insertIndex].Size;
                 }
                 else
                 {
                     result = PDFViewer.Document.InsertPage(insertIndex, PageEditItems[insertIndex-1].Size.Width, PageEditItems[insertIndex-1].Size.Height, null);
+                    history.PageSize = PageEditItems[insertIndex - 1].Size;
                 }
                 if(!result)
                 {
                     IsLoading = Visibility.Collapsed;
-                    ShowTip = Visibility.Visible;
+                    ShowToast();
                     return;
                 }
 
@@ -454,7 +516,8 @@ namespace PDF_Office.ViewModels.PageEdit
 
                 ReloadAfterOption(true,true,Tuple.Create(insertIndex,insertIndex+1));
                 await Task.Delay(10);
-                ListSelectedIndex = insertIndex == 0 ? insertIndex : insertIndex;
+                //选中插入的页面
+                ListSelectedIndex = insertIndex;
             }
             else if((string)type == ParameterNames.InsertType_File)
             {
@@ -468,12 +531,15 @@ namespace PDF_Office.ViewModels.PageEdit
                     if(!result)
                     {
                         IsLoading = Visibility.Collapsed;
-                        ShowTip = Visibility.Visible;
+                        ShowToast();
                         return;
                     }
 
                     ReloadAfterOption(true,true,Tuple.Create(0,PDFViewer.Document.PageCount));
                 }
+                IsLoading = Visibility.Collapsed;
+                //里面附带了Undo栈记录,需要提前返回,避免重复记录
+                return;
             }
             else
             {
@@ -485,22 +551,23 @@ namespace PDF_Office.ViewModels.PageEdit
                     {
                         var model = e.Parameters.GetValue<CustomInsertModel>(ParameterNames.DataModel);
 
-                        var pageIndex = ListSelectedIndex;
-                        //文档层插入
-                        var result = PDFViewer.Document.InsertPage(pageIndex, model.width,model.height,model.filepath);
+                        var result = InsertFromCustomPage(insertIndex, model.width, model.height, model.filepath);
                         if(!result)
                         {
-                            ShowTip = Visibility.Visible;
                             return;
                         }
-                        PageEditItem item = new PageEditItem();
-                        PageEditItems.Insert(pageIndex, item);
-                        ReloadAfterOption(true,true,Tuple.Create(pageIndex-1,pageIndex+1));
+
+                        history.Type = ActionType.InsertCustomPages;
+                        history.InsertFilePath = model.filepath;
+                        history.PageSize = new Size(model.width,model.height);
 
                     }
                 });
             }
             IsLoading = Visibility.Collapsed;
+
+            //添加记录到Undo栈,清除Redo栈
+            AddToUndoStack(history);
         }
 
         /// <summary>
@@ -567,7 +634,7 @@ namespace PDF_Office.ViewModels.PageEdit
                 var result = PDFViewer.Document.ExchangePage(preindex, laterIndex);
                 if(!result)
                 {
-                    ShowTip = Visibility.Visible;
+                     ShowToast();
                     IsLoading = Visibility.Collapsed;
                     return;
                 }
@@ -579,11 +646,16 @@ namespace PDF_Office.ViewModels.PageEdit
             }
 
             await Task.Delay(20);
+            //转换成页码数据集合,传递给UI,选中目标页面
+            //因虚拟化加载的问题,通过Selected来控制Item选中效果会有问题
+            List<int> pageRange = new List<int>();
             for(int i=0;i<pages.Count;i++)
             {
-                PageEditItems[i].Selected = true;
+                pageRange.Add(pages[i]+1);
             }
 
+            NotifyUIToRefresh(pageRange);
+
             ReloadAfterOption(true,true,null);
             IsLoading = Visibility.Collapsed;
         }
@@ -691,55 +763,41 @@ namespace PDF_Office.ViewModels.PageEdit
         /// <param name="e"></param>
         private void SelectionChangedEvent(object e)
         {
-            //var args = e as SelectionChangedEventArgs;
-            //var listbox = args.OriginalSource as ListBox;
-            //if (TbPageRangeVisibility == Visibility.Visible && args != null)
-            //{
-            //    List<int> pagelist = new List<int>();
-            //    for (int i = 0; i < listbox.SelectedItems.Count; i++)
-            //    {
-            //        if (!pagelist.Contains((listbox.SelectedItems[i] as PageEditItem).PageNumber))
-            //        {
-            //            pagelist.Add((listbox.SelectedItems[i] as PageEditItem).PageNumber);
-            //        }
-            //    }
-
-            //    ////手动取消其他项的选中状态
-            //    //for (int j = 0; j < PageEditItems.Count; j++)
-            //    //{
-            //    //    if (!pagelist.Contains(PageEditItems[j].PageNumber))
-            //    //    {
-            //    //        PageEditItems[j].Selected = false;
-            //    //    }
-            //    //}
-
-            //    ////根据选中的范围 适配全部页面范围、奇数页面范围等
-            //    //if(pagelist.Count==PageEditItems.Count)
-            //    //{
-            //    //    ComboxSelectIndex = 0;
-            //    //    return;
-            //    //}
-
-            //    string pageparm = CommonHelper.GetPageParmFromList(pagelist);
-            //    TbPageRange = pageparm;
-
-
-            //}
-            //if (listbox.SelectedItem != null)
-            //{
-            //    listbox.ScrollIntoView(listbox.SelectedItem);
-            //}
-
-            ////判断是否有选中多项
-            //if (listbox.SelectedItems.Count > 1)
-            //{
-            //    IsMutiSelected = true;
-            //    maxSelectedIndex = listbox.Items.IndexOf(listbox.SelectedItems[listbox.SelectedItems.Count-1]);
-            //}
-            //else
-            //{
-            //    IsMutiSelected = false;
-            //}
+            var args = e as SelectionChangedEventArgs;
+            //下下策 从UI控件获取所有选项的集合
+            var listbox = args.OriginalSource as ListBox;
+            if (TbPageRangeVisibility == Visibility.Visible && args != null)
+            {
+                List<int> pagelist = new List<int>();
+                for (int i = 0; i < listbox.SelectedItems.Count; i++)
+                {
+                    if (!pagelist.Contains((listbox.SelectedItems[i] as PageEditItem).PageNumber))
+                    {
+                        pagelist.Add((listbox.SelectedItems[i] as PageEditItem).PageNumber);
+                    }
+                }
+
+                ////根据选中的范围 适配全部页面范围、奇数页面范围等
+                //if (pagelist.Count == PageEditItems.Count)
+                //{
+                //    ComboxSelectIndex = 0;
+                //    return;
+                //}
+
+                string pageparm = CommonHelper.GetPageParmFromList(pagelist);
+                TbPageRange = pageparm;
+            }
+
+            //判断是否有选中多项
+            if (listbox.SelectedItems.Count > 1)
+            {
+                IsMultiSelected = true;
+                maxSelectedIndex = listbox.Items.IndexOf(listbox.SelectedItems[listbox.SelectedItems.Count - 1]);
+            }
+            else
+            {
+                IsMultiSelected = false;
+            }
         }
 
         /// <summary>
@@ -783,23 +841,120 @@ namespace PDF_Office.ViewModels.PageEdit
                 }
 
                 //选中输入的页面范围
+                List<int> pageRange = new List<int>();
                 for (int i = 0; i < PageEditItems.Count; i++)
                 {
                     if (TargetPageIndexs.Contains(PageEditItems[i].PageNumber - 1))
                     {
-                        PageEditItems[i].Selected = true;
-                    }
-                    else
-                    {
-                        PageEditItems[i].Selected = false;
+                        pageRange.Add(i+1);
                     }
                 }
+
+                NotifyUIToRefresh(pageRange);
             }
         }
 
         #endregion
 
         #region 方法
+
+        /// <summary>
+        /// 页面编辑执行Undo操作的方法
+        /// </summary>
+        private void Undo()
+        {
+            var history = UndoStack.Pop();
+            PageEditHistory redoHistory = new PageEditHistory();
+            switch (history.Type)
+            {
+                case ActionType.RightRotate:
+                    var rightlist = history.SourceTargetValue.Keys.ToList<int>();
+                    RotateSelectedPages(false, rightlist,true);
+
+                    redoHistory.SourceTargetValue = history.SourceTargetValue;
+                    redoHistory.Type = ActionType.LeftRotate;
+                    break;
+                case ActionType.LeftRotate:
+                    var leftlist = history.SourceTargetValue.Keys.ToList<int>();
+                    RotateSelectedPages(true, leftlist,true);
+
+                    redoHistory.SourceTargetValue = history.SourceTargetValue;
+                    redoHistory.Type = ActionType.RightRotate;
+                    break;
+                case ActionType.InsertFromFile:
+                    List<int> pageList = new List<int>();
+                    for(int i=0;i<history.InsertPageCount;i++)
+                    {
+                        pageList.Add(history.InsertIndex+i);
+                    }
+                    DoRemoveSelectedPages(pageList, true);
+                    redoHistory = history;
+                    break;
+                case ActionType.InsertCustomPages:
+                    DoRemoveSelectedPages(new List<int> {history.InsertIndex},true);
+                    redoHistory = history;
+                    break;
+                case ActionType.DragSort:
+                    break;
+                default:
+                    break;
+            }
+            RedoStack.Push(redoHistory);
+            CanRedo = true;
+            //检查是否可以再进行Undo
+            if(UndoStack.Count<=0)
+            {
+                this.CanUndo = false;
+            }
+        }
+
+        /// <summary>
+        /// 页面编辑执行Redo操作的方法
+        /// </summary>
+        private void Redo()
+        {
+            var history = RedoStack.Pop();
+            PageEditHistory undoHistory = new PageEditHistory();
+            switch (history.Type)
+            {
+                case ActionType.RightRotate:
+                    var rightlist = history.SourceTargetValue.Keys.ToList<int>();
+                    RotateSelectedPages(false, rightlist,true);
+
+                    undoHistory.SourceTargetValue = history.SourceTargetValue;
+                    undoHistory.Type = ActionType.LeftRotate;
+                    break;
+                case ActionType.LeftRotate:
+                    var leftlist = history.SourceTargetValue.Keys.ToList<int>();
+                    RotateSelectedPages(true, leftlist,true);
+
+                    undoHistory.SourceTargetValue = history.SourceTargetValue;
+                    undoHistory.Type = ActionType.RightRotate;
+                    break;
+                case ActionType.InsertFromFile:
+                    InsertFromFile(history.InsertIndex,history.InsertFilePath,history.InsertFilePassWord,true);
+                    //刷新图片
+                    ReloadAfterOption(true, true, Tuple.Create(history.InsertIndex - 1, history.InsertIndex+history.InsertPageCount));
+                    undoHistory = history;
+                    break;
+                case ActionType.InsertCustomPages:
+                    InsertFromCustomPage(history.InsertIndex, history.PageSize.Width, history.PageSize.Height, history.InsertFilePath);
+                    ListSelectedIndex = history.InsertIndex;
+                    undoHistory = history;
+                    break;
+                case ActionType.DragSort:
+                    break;
+                default:
+                    break;
+            }
+            UndoStack.Push(undoHistory);
+            CanUndo = true;
+            if (RedoStack.Count <= 0)
+            {
+                this.CanRedo = false;
+            }
+        }
+
         /// <summary>
         /// 退出页面编辑面试,回到阅读页
         /// </summary>
@@ -812,7 +967,7 @@ namespace PDF_Office.ViewModels.PageEdit
         /// <summary>
         /// 显示Toast提示
         /// </summary>
-        private void ShowToast(string content)
+        private void ShowToast(string content="")
         {
             if (!string.IsNullOrEmpty(content))
             {
@@ -847,7 +1002,7 @@ namespace PDF_Office.ViewModels.PageEdit
         /// 删除选中项的方法 不带Reload操作
         /// 方便其他逻辑中调用
         /// </summary>
-        private void DoRemoveSelectedPages(List<int> pageList = null)
+        private void DoRemoveSelectedPages(List<int> pageList = null, bool isFromUndoRedo = false)
         {
             List<int> indexList = new List<int>();
             if (pageList == null || pageList.Count < 0)
@@ -875,7 +1030,7 @@ namespace PDF_Office.ViewModels.PageEdit
             var result = PDFViewer.Document.RemovePages(indexList.ToArray());
             if (!result)
             {
-                ShowTip = Visibility.Visible;
+                 ShowToast();
                 return;
             }
 
@@ -884,6 +1039,15 @@ namespace PDF_Office.ViewModels.PageEdit
             {
                 PageEditItems.RemoveAt(indexList[i]);
             }
+
+            if (!isFromUndoRedo)
+            {
+                //清除页面编辑Undo,Redo栈
+                UndoStack.Clear();
+                RedoStack.Clear();
+                this.CanUndo = false;
+                this.CanRedo = false;
+            }
         }
 
         /// <summary>
@@ -954,14 +1118,14 @@ namespace PDF_Office.ViewModels.PageEdit
                 bool result = savedoc.ImportPages(PDFViewer.Document, range);
                 if (!result)
                 {
-                    ShowTip = Visibility.Visible;
+                     ShowToast();
                     IsLoading = Visibility.Collapsed;
                     return;
                 }
                 result = savedoc.WriteToFilePath(path);
                 if (!result)
                 {
-                    ShowTip = Visibility.Visible;
+                     ShowToast();
                 }
                 savedoc.Release();//释放内存
             }
@@ -1099,14 +1263,14 @@ namespace PDF_Office.ViewModels.PageEdit
                     if (!result)
                     {
                         saveDoc1.Release();
-                        ShowTip = Visibility.Visible;
+                         ShowToast();
                         return;
                     }
                     result = saveDoc1.WriteToFilePath(path1);
                     if (!result)
                     {
                         saveDoc1.Release();
-                        ShowTip = Visibility.Visible;
+                         ShowToast();
                         return;
                     }
                     saveDoc1.Release();
@@ -1126,14 +1290,14 @@ namespace PDF_Office.ViewModels.PageEdit
                     if (!result)
                     {
                         saveDoc2.Release();
-                        ShowTip = Visibility.Visible;
+                         ShowToast();
                         return;
                     }
                     result = saveDoc2.WriteToFilePath(path2);
                     if (!result)
                     {
                         saveDoc2.Release();
-                        ShowTip = Visibility.Visible;
+                         ShowToast();
                         return;
                     }
                     selectedfile = path1;
@@ -1152,29 +1316,44 @@ namespace PDF_Office.ViewModels.PageEdit
         /// 将文件插入到指定位置
         /// </summary>
         /// <param name="insertIndex"></param>
-        private async Task<bool> InsertFromFile(int insertIndex,string filePath)
+        public async Task<bool> InsertFromFile(int insertIndex, string filePath, string oldPassWord = null, bool isFromUndoRedo = false)
         {
             CPDFDocument doc = CPDFDocument.InitWithFilePath(filePath);
             if (doc == null)
             {
-                showTip = Visibility.Visible;
+                 ShowToast();
                 return false;
             }
+            string password = "";
             if (doc.IsLocked)
             {
-                DialogParameters value = new DialogParameters();
-                value.Add(ParameterNames.PDFDocument, doc);
-                bool result = true;
-                dialogs.ShowDialog(DialogNames.VerifyPassWordDialog, value,e=>
+                if(!string.IsNullOrEmpty(oldPassWord))
                 {
-                    if (e.Result != ButtonResult.OK)
+                    var result =  doc.UnlockWithPassword(oldPassWord);
+                    if(result)
                     {
-                        result = false;
+                        password = oldPassWord;
                     }
-                });
-                if(!result)
+                }
+
+                //没有传入密码,或者用传入密码解密失败是,需要弹出界面弹窗
+                if (doc.IsLocked)
                 {
-                    return false;
+                    DialogParameters value = new DialogParameters();
+                    value.Add(ParameterNames.PDFDocument, doc);
+                    bool result = true;
+                    dialogs.ShowDialog(DialogNames.VerifyPassWordDialog, value, e =>
+                     {
+                         if (e.Result != ButtonResult.OK)
+                         {
+                             result = false;
+                         }
+                         password = e.Parameters.GetValue<string>(ParameterNames.PassWord);
+                     });
+                    if (!result)
+                    {
+                        return false;
+                    }
                 }
             }
 
@@ -1182,18 +1361,16 @@ namespace PDF_Office.ViewModels.PageEdit
 
             //插入整个新文档
             //文档层插入
-            await Task.Run(() =>
+
+            var insertresult = PDFViewer.Document.ImportPagesAtIndex(doc, "1-" + pageCount, insertIndex);
+            if (!insertresult)
             {
-                var result = PDFViewer.Document.ImportPagesAtIndex(doc, "1-" + pageCount, insertIndex);
-                if (!result)
-                {
-                    ShowTip = Visibility.Visible;
-                    return false;
-                }
-                    //插入成功后释放临时Document对象
-                    doc.Release();
-                return true;
-            });
+                ShowToast();
+                return false;
+            }
+            //插入成功后释放临时Document对象
+            doc.Release();
+
 
             //UI层插入
             for (int i = 0; i < pageCount; i++)
@@ -1203,15 +1380,65 @@ namespace PDF_Office.ViewModels.PageEdit
             }
 
             //加一点延时才能显示选中效果
-            await Task.Delay(400);
-
+            await Task.Delay(200);
+            List<int> pageRange = new List<int>();
             for (int i = 0; i < pageCount; i++)
             {
-                PageEditItems[insertIndex + i].Selected = true;
+                pageRange.Add(insertIndex+i+1);
+            }
+            NotifyUIToRefresh(pageRange);
+
+            //如果是undo redo里调用本方法,则不需要添加到Undo栈
+            if (!isFromUndoRedo)
+            {
+                //添加记录到Undo栈,清空Redo栈
+                PageEditHistory history = new PageEditHistory();
+                history.Type = ActionType.InsertFromFile;
+                history.InsertIndex = insertIndex;
+                history.InsertFilePath = filePath;
+                history.InsertFilePassWord = password;
+                history.InsertPageCount = pageCount;
+
+                AddToUndoStack(history);
             }
             return true;
         }
 
+        /// <summary>
+        /// 添加记录到Undo栈
+        /// </summary>
+        /// <param name="history"></param>
+        private void AddToUndoStack(PageEditHistory history)
+        {
+            UndoStack.Push(history);
+            CanUndo = true;
+            RedoStack.Clear();
+            CanRedo = false;
+        }
+
+        /// <summary>
+        /// 插入自定义页面
+        /// </summary>
+        /// <param name="insertIndex"></param>
+        /// <param name="width"></param>
+        /// <param name="height"></param>
+        /// <param name="filePath"></param>
+        /// <returns></returns>
+        private bool InsertFromCustomPage(int insertIndex,double width,double height,string filePath)
+        {
+            //文档层插入
+            var result = PDFViewer.Document.InsertPage(insertIndex, width, height, string.IsNullOrEmpty(filePath)?null:filePath);
+            if (!result)
+            {
+                ShowToast();
+                return false;
+            }
+            PageEditItem item = new PageEditItem();
+            PageEditItems.Insert(insertIndex, item);
+            ReloadAfterOption(true, true, Tuple.Create(insertIndex - 1, insertIndex + 1));
+            return true;
+        }
+
         /// <summary>
         /// 根据索引创建新的Item
         /// </summary>
@@ -1228,7 +1455,9 @@ namespace PDF_Office.ViewModels.PageEdit
             item.PageNumber = index + 1;
             var pagesize = PDFViewer.Document.GetPageSize(index);
             item.Size = pagesize;
-            item.PageSize = $"{pagesize.Width}mm*{pagesize.Height} mm";
+            double width = CommonHelper.GetUnitsFromPageSize(pagesize.Width);
+            double height = CommonHelper.GetUnitsFromPageSize(pagesize.Height);
+            item.PageSize = $"{width.ToString("F2")}mm*{height.ToString("F2")} mm";
             return item;
         }
 
@@ -1266,27 +1495,59 @@ namespace PDF_Office.ViewModels.PageEdit
             PDFViewer.UndoManager.CanSave = true;
             PDFViewer.ReloadDocument();
         }
+
         /// <summary>
         /// 旋转所有选中页面
         /// </summary>
         /// <param name="rightRotate"></param>
-        private async void RotateSelectedPages(bool rightRotate = true)
+        private async void RotateSelectedPages(bool rightRotate = true,List<int> pageitems=null,bool isFromUndoRedo = false)
         {
             IsLoading = Visibility.Visible;
             await Task.Delay(2);
-            for (int i = 0; i < PageEditItems.Count; i++)
+            Dictionary<int, int> items = new Dictionary<int, int>();
+            if (pageitems == null)
             {
-                if (PageEditItems[i].Selected)
+                //旋转选中页面
+                for (int i = 0; i < PageEditItems.Count; i++)
+                {
+                    if (PageEditItems[i].Selected)
+                    {
+                        //逆时针旋转传 - 1  顺时针旋转传1
+                        PDFViewer.Document.RotatePage(i, rightRotate ? 1 : -1);
+                        PDFViewer.Document.ReleasePages(i);
+                        items.Add(i, i);
+
+                        //重新拿图
+                        PageEditItems[i].isVertical = !PageEditItems[i].isVertical;
+                        PageEditItems[i].IsGetImage = false;
+                    }
+                }
+            }
+            else
+            {
+                //旋转对应Items集合
+                for (int i = 0; i < pageitems.Count; i++)
                 {
-                    //逆时针旋转传 - 1  顺时针旋转传1
-                    PDFViewer.Document.RotatePage(i, rightRotate ? 1 : -1);
-                    PDFViewer.Document.ReleasePages(i);
+                    PDFViewer.Document.RotatePage(pageitems[i], rightRotate ? 1 : -1);
+                    PDFViewer.Document.ReleasePages(pageitems[i]);
+                    items.Add(pageitems[i], pageitems[i]);
 
                     //重新拿图
-                    PageEditItems[i].isVertical = !PageEditItems[i].isVertical;
-                    PageEditItems[i].IsGetImage = false;
+                    PageEditItems[pageitems[i]].isVertical = !PageEditItems[pageitems[i]].isVertical;
+                    PageEditItems[pageitems[i]].IsGetImage = false;
                 }
             }
+
+            //如果是undo,Redo里调用的方法,则不记录到栈里
+            if (!isFromUndoRedo)
+            {
+                //记录进Undo栈
+                PageEditHistory history = new PageEditHistory();
+                history.Type = rightRotate ? ActionType.RightRotate : ActionType.LeftRotate;
+                history.SourceTargetValue = items;
+                AddToUndoStack(history);
+            }
+
             ReloadAfterOption(false, true, Tuple.Create(0, PageEditItems.Count));
             IsLoading = Visibility.Collapsed;
         }
@@ -1299,7 +1560,9 @@ namespace PDF_Office.ViewModels.PageEdit
             for (int i = 0; i < PageEditItems.Count; i++)
             {
                 PageEditItems[i].PageNumber = i + 1;
+                PageEditItems[i].ShowPageSize = HasShowPageSize == Visibility.Visible ? true : false;
             }
+            
         }
 
         /// <summary>
@@ -1323,12 +1586,13 @@ namespace PDF_Office.ViewModels.PageEdit
         /// <param name="index">页面范围选中项索引</param>
         private void SuitPageRange(int index)
         {
+            List<int> pageRange = new List<int>();
             switch (index)
             {
                 case 0:
                     for (int i = 0; i < PageEditItems.Count; i++)
                     {
-                        PageEditItems[i].Selected = true;
+                        pageRange.Add(i+1);
                     }
                     break;
 
@@ -1338,11 +1602,7 @@ namespace PDF_Office.ViewModels.PageEdit
                     {
                         if (i % 2 == 0)
                         {
-                            PageEditItems[i].Selected = true;
-                        }
-                        else
-                        {
-                            PageEditItems[i].Selected = false;
+                            pageRange.Add(i + 1);
                         }
                     }
                     break;
@@ -1350,26 +1610,18 @@ namespace PDF_Office.ViewModels.PageEdit
                     //偶数页
                     for (int i = 0; i < PageEditItems.Count; i++)
                     {
-                        if (i % 2 == 0)
+                        if (i % 2 != 0)
                         {
-                            PageEditItems[i].Selected = false;
-                        }
-                        else
-                        {
-                            PageEditItems[i].Selected = true;
+                            pageRange.Add(i + 1);
                         }
                     }
                     break;
                 case 3://横向页面
                     for (int i = 0; i < PageEditItems.Count; i++)
                     {
-                        if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0)
+                        if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 != 0)
                         {
-                            PageEditItems[i].Selected = false;
-                        }
-                        else
-                        {
-                            PageEditItems[i].Selected = true;
+                            pageRange.Add(i + 1);
                         }
                     }
                     break;
@@ -1378,11 +1630,7 @@ namespace PDF_Office.ViewModels.PageEdit
                     {
                         if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0)
                         {
-                            PageEditItems[i].Selected = true;
-                        }
-                        else
-                        {
-                            PageEditItems[i].Selected = false;
+                            pageRange.Add(i + 1);
                         }
                     }
                     break;
@@ -1394,6 +1642,10 @@ namespace PDF_Office.ViewModels.PageEdit
                 default:
                     break;
             }
+            if(pageRange.Count>0)
+            {
+                NotifyUIToRefresh(pageRange);
+            }
         }
 
 
@@ -1401,8 +1653,19 @@ namespace PDF_Office.ViewModels.PageEdit
         /// 是否显示页面尺寸
         /// </summary>
         /// <param name="show">是或否</param>
-        private void ShowPageSize(bool show = true)
+        private void ShowPageSize()
         {
+            bool show = true;
+            if(HasShowPageSize== Visibility.Visible)
+            {
+                show = false;
+                HasShowPageSize = Visibility.Collapsed;
+            }
+            else
+            {
+                show = true;
+                HasShowPageSize = Visibility.Visible;
+            }
             for (int i = 0; i < PageEditItems.Count; i++)
             {
                 PageEditItems[i].ShowPageSize = show;
@@ -1542,10 +1805,15 @@ namespace PDF_Office.ViewModels.PageEdit
             {
                 if (isFirstLoad)
                 {
+                    PDFViewer.OnThumbnailGenerated -= PDFViewer_OnThumbnailGenerated;
                     PDFViewer.OnThumbnailGenerated += PDFViewer_OnThumbnailGenerated;
                     PDFViewer.InfoChanged += PDFViewer_InfoChanged;
                     ZoomIndex = 0;
-
+                    if(viewContentViewModel!=null)
+                    {
+                        viewContentViewModel.PageEditUndo = Undo;
+                        viewContentViewModel.PageEditRedo = Redo;
+                    }
                 }
                 //BOTA缩略图时,显示不同的菜单栏
                 if(isBOTA)

+ 42 - 9
PDF Office/Views/Dialog/PageEditDialogs/InsertDialog.xaml

@@ -24,18 +24,33 @@
             <convert:FileToImageSourceConvert x:Key="FileToImageSourceConvert" />
             <DataTemplate x:Key="CustomItem" DataType="{x:Type model:CustomPageItem}">
                 <StackPanel HorizontalAlignment="Center">
-                    <Border>
-                        <Image
-                            Width="208"
-                            Height="230"
-                            Source="{Binding FilePath, Converter={StaticResource FileToImageSourceConvert}}" />
+                    <Border
+                        Name="BdBorder"
+                        Width="104"
+                        Height="64"
+                        BorderBrush="#A0A2AE"
+                        BorderThickness="1"
+                        CornerRadius="6">
+                        <Border.Background>
+                            <ImageBrush ImageSource="{Binding FilePath, Converter={StaticResource FileToImageSourceConvert}}" />
+                        </Border.Background>
                     </Border>
                     <Label
+                        Name="LbPageNum"
                         Width="auto"
                         Margin="0,4,0,0"
+                        HorizontalAlignment="Center"
+                        Background="Transparent"
                         Content="{Binding Name}"
                         FontSize="12" />
                 </StackPanel>
+                <DataTemplate.Triggers>
+                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
+                        <Setter TargetName="BdBorder" Property="BorderBrush" Value="#118AFF" />
+                        <Setter TargetName="BdBorder" Property="CornerRadius" Value="4" />
+                        <Setter TargetName="LbPageNum" Property="Foreground" Value="#118AFF" />
+                    </DataTrigger>
+                </DataTemplate.Triggers>
             </DataTemplate>
         </ResourceDictionary>
     </UserControl.Resources>
@@ -48,10 +63,18 @@
                     <RowDefinition Height="auto" />
                 </Grid.RowDefinitions>
                 <ListBox
+                    Padding="0,16,0,0"
+                    HorizontalAlignment="Center"
                     BorderThickness="0"
                     ItemTemplate="{StaticResource CustomItem}"
                     ItemsSource="{Binding Pages}"
                     SelectedIndex="{Binding ItemSelectedIndex, Mode=TwoWay}">
+                    <ListBox.ItemContainerStyle>
+                        <Style TargetType="{x:Type ListBoxItem}">
+                            <Setter Property="Template" Value="{StaticResource ListBoxItemControlTemplate}" />
+                            <Setter Property="FocusVisualStyle" Value="{x:Null}" />
+                        </Style>
+                    </ListBox.ItemContainerStyle>
                     <ListBox.ItemsPanel>
                         <ItemsPanelTemplate>
                             <WrapPanel />
@@ -83,16 +106,19 @@
                     </StackPanel>
                     <StackPanel Margin="0,12" Orientation="Horizontal">
                         <RadioButton
+                            Name="RbtnStandard"
                             VerticalAlignment="Center"
                             Content="标准"
                             GroupName="PageSize" />
                         <ComboBox
                             Width="228"
                             Height="32"
-                            Margin="8,0" />
+                            Margin="8,0"
+                            IsEnabled="{Binding ElementName=RbtnStandard, Path=IsChecked}" />
                     </StackPanel>
                     <StackPanel Margin="0,0,0,12" Orientation="Horizontal">
                         <RadioButton
+                            Name="RbtnCustom"
                             VerticalAlignment="Center"
                             Content="自定义"
                             GroupName="PageSize" />
@@ -100,16 +126,23 @@
                             Width="80"
                             Height="32"
                             Margin="8,0"
-                            VerticalAlignment="Center"
+                            VerticalContentAlignment="Center"
+                            IsEnabled="{Binding ElementName=RbtnCustom, Path=IsChecked}"
                             Text="{Binding CustomWidth, Mode=TwoWay}" />
                         <TextBlock VerticalAlignment="Center" Text="X" />
                         <TextBox
                             Width="80"
                             Height="32"
                             Margin="8,0"
-                            VerticalAlignment="Center"
+                            VerticalContentAlignment="Center"
+                            IsEnabled="{Binding ElementName=RbtnCustom, Path=IsChecked}"
                             Text="{Binding CustomHeight, Mode=TwoWay}" />
-                        <ComboBox Width="80" />
+                        <ComboBox
+                            Width="80"
+                            VerticalContentAlignment="Center"
+                            IsEnabled="{Binding ElementName=RbtnCustom, Path=IsChecked}"
+                            ItemsSource="{Binding Units}"
+                            SelectedIndex="{Binding UnitsSelectedIndex}" />
                     </StackPanel>
                 </StackPanel>
                 <StackPanel Grid.Row="2" Margin="16,0">

+ 34 - 16
PDF Office/Views/PageEdit/PageEditContent.xaml

@@ -13,6 +13,7 @@
     xmlns:pageedit="clr-namespace:PDF_Office.Model.PageEdit"
     xmlns:pageedit1="clr-namespace:PDF_Office.ViewModels.PageEdit"
     xmlns:prism="http://prismlibrary.com/"
+    xmlns:viewmodel="clr-namespace:PDF_Office.ViewModels.PageEdit"
     xmlns:wpftk="clr-namespace:WpfToolkit.Controls;assembly=VirtualizingWrapPanel"
     Name="PageEdit"
     d:DataContext="{d:DesignInstance Type=pageedit1:PageEditContentViewModel}"
@@ -25,6 +26,7 @@
     <UserControl.Resources>
         <ResourceDictionary>
             <convert:BoolToVisible x:Key="BoolToVisibleConvert" />
+            <convert:UnVisivleConvert x:Key="UnVisibleConvert" />
             <DataTemplate x:Key="PageEditListBoxItemTemplate" DataType="{x:Type pageedit:PageEditItem}">
                 <StackPanel>
                     <Border
@@ -84,7 +86,7 @@
                     <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
                         <Setter TargetName="BdBorder" Property="BorderBrush" Value="Blue" />
                         <Setter TargetName="BdBorder" Property="CornerRadius" Value="4" />
-                        <Setter TargetName="BdPageNum" Property="Background" Value="Blue" />
+                        <Setter TargetName="BdPageNum" Property="Background" Value="blue" />
                         <Setter TargetName="BdPageNum" Property="CornerRadius" Value="4" />
                     </DataTrigger>
                     <MultiDataTrigger>
@@ -93,29 +95,45 @@
                             <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="False" />
                         </MultiDataTrigger.Conditions>
                         <MultiDataTrigger.Setters>
-                            <Setter TargetName="BdBorder" Property="BorderBrush" Value="Blue" />
+                            <Setter TargetName="BdBorder" Property="BorderBrush" Value="#68ACF8" />
                             <Setter TargetName="BdBorder" Property="CornerRadius" Value="4" />
                         </MultiDataTrigger.Setters>
                     </MultiDataTrigger>
                 </DataTemplate.Triggers>
             </DataTemplate>
 
-            <ContextMenu x:Key="ListBoxItemMenu">
+            <ContextMenu x:Key="ListBoxItemMenu" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">
                 <MenuItem Header="插入页面">
-                    <MenuItem Header="插入文件" />
-                    <MenuItem Header="插入空白页" />
-                    <MenuItem Header="插入自定义页面" />
+                    <MenuItem
+                        Command="{Binding InsertCommand}"
+                        CommandParameter="{x:Static model:ParameterNames.InsertType_File}"
+                        Header="插入文件" />
+                    <MenuItem
+                        Command="{Binding InsertCommand}"
+                        CommandParameter="{x:Static model:ParameterNames.InsertType_Blank}"
+                        Header="插入空白页" />
+                    <MenuItem
+                        Command="{Binding InsertCommand}"
+                        CommandParameter="{x:Static model:ParameterNames.InsertType_Custom}"
+                        Header="插入自定义页面" />
                 </MenuItem>
-                <MenuItem Header="提取页面" />
-                <MenuItem Header="替换页面" />
-                <MenuItem Header="删除页面" />
-                <MenuItem Header="删除页面" />
-                <MenuItem Header="顺时针旋转页面" />
-                <MenuItem Header="逆时针旋转页面" />
+                <MenuItem Command="{Binding ExtractCommand}" Header="提取页面" />
+                <MenuItem Command="{Binding ReplaceCommand}" Header="替换页面" />
+                <MenuItem Command="{Binding DeleteCommand}" Header="删除页面" />
+                <MenuItem Command="{Binding RightRotateCommand}" Header="顺时针旋转页面" />
+                <MenuItem Command="{Binding LeftRotateCommand}" Header="逆时针旋转页面" />
                 <MenuItem Header="复制" />
                 <MenuItem Header="剪切" />
                 <MenuItem Header="粘贴" />
-                <MenuItem Header="显示页面大小" />
+                <MenuItem
+                    Command="{Binding ShowPageSizeCommand}"
+                    Header="显示页面大小"
+                    Visibility="{Binding Source={x:Reference Name=MenuHidePageSize}, Path=Visibility, Converter={StaticResource UnVisibleConvert}}" />
+                <MenuItem
+                    Name="MenuHidePageSize"
+                    Command="{Binding ShowPageSizeCommand}"
+                    Header="隐藏页面大小"
+                    Visibility="{Binding HasShowPageSize}" />
                 <MenuItem Header="打印页面" />
             </ContextMenu>
         </ResourceDictionary>
@@ -318,7 +336,7 @@
                         <Setter Property="Template" Value="{StaticResource ListBoxItemControlTemplate}" />
                         <Setter Property="Margin" Value="0,10" />
                         <Setter Property="Visibility" Value="{Binding Visible}" />
-                        <Setter Property="IsSelected" Value="{Binding Selected, Mode=TwoWay}" />
+                        <Setter Property="IsSelected" Value="{Binding Selected, Mode=OneWayToSource}" />
                         <Setter Property="HorizontalAlignment" Value="Center" />
                         <Setter Property="VerticalAlignment" Value="Center" />
                         <Setter Property="HorizontalContentAlignment" Value="Center" />
@@ -381,7 +399,7 @@
                 Grid.Row="1"
                 Width="auto"
                 Height="auto"
-                Margin="0,0,0,200"
+                Margin="0,0,0,100"
                 VerticalAlignment="Bottom"
                 Background="#89000000"
                 BeginTime="0:0:0:3"
@@ -389,7 +407,7 @@
                 FontSize="14"
                 Foreground="White"
                 StringContent="{Binding ToastText}"
-                Visibility="{Binding ShowTip}"
+                Visibility="{Binding ShowTip, Mode=TwoWay}"
                 Duration="0:0:0:3" />
             <ProgressBar
                 Grid.Row="1"