diff --git a/Constant/DefaultConstant.cs b/Constant/DefaultConstant.cs index 33b95f7..56a286b 100644 --- a/Constant/DefaultConstant.cs +++ b/Constant/DefaultConstant.cs @@ -7,6 +7,8 @@ namespace GeekDesk.Constant { WINDOW_WIDTH = 650, //默认窗体宽度 WINDOW_HEIGHT = 700, //默认窗体高度 - MENU_CARD_WIDHT = 150 //默认菜单栏宽度 + MENU_CARD_WIDHT = 150, //默认菜单栏宽度 + IMAGE_WIDTH = 60, //默认图标宽度 + IMAGE_HEIGHT = 60, //默认图标高度 } } diff --git a/EditTextBlock/EditableTextBlock.cs b/EditTextBlock/EditableTextBlock.cs new file mode 100644 index 0000000..57c1a02 --- /dev/null +++ b/EditTextBlock/EditableTextBlock.cs @@ -0,0 +1,135 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; + +namespace GeekDesk.EditTextBlock +{ + public class EditableTextBlock : TextBlock + { + public bool IsInEditMode + { + get + { + return (bool)GetValue(IsInEditModeProperty); + } + set + { + SetValue(IsInEditModeProperty, value); + } + } + + private EditableTextBlockAdorner _adorner; + + // Using a DependencyProperty as the backing store for IsInEditMode. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsInEditModeProperty = + DependencyProperty.Register("IsInEditMode", typeof(bool), typeof(EditableTextBlock), new UIPropertyMetadata(false, IsInEditModeUpdate)); + + /// + /// Determines whether [is in edit mode update] [the specified obj]. + /// + /// The obj. + /// The instance containing the event data. + private static void IsInEditModeUpdate(DependencyObject obj, DependencyPropertyChangedEventArgs e) + { + EditableTextBlock textBlock = obj as EditableTextBlock; + if (null != textBlock) + { + //Get the adorner layer of the uielement (here TextBlock) + AdornerLayer layer = AdornerLayer.GetAdornerLayer(textBlock); + + //If the IsInEditMode set to true means the user has enabled the edit mode then + //add the adorner to the adorner layer of the TextBlock. + if (textBlock.IsInEditMode) + { + if (null == textBlock._adorner) + { + textBlock._adorner = new EditableTextBlockAdorner(textBlock); + + //Events wired to exit edit mode when the user presses Enter key or leaves the control. + textBlock._adorner.TextBoxKeyUp += textBlock.TextBoxKeyUp; + textBlock._adorner.TextBoxLostFocus += textBlock.TextBoxLostFocus; + } + layer.Add(textBlock._adorner); + } + else + { + //Remove the adorner from the adorner layer. + Adorner[] adorners = layer.GetAdorners(textBlock); + if (adorners != null) + { + foreach (Adorner adorner in adorners) + { + if (adorner is EditableTextBlockAdorner) + { + layer.Remove(adorner); + } + } + } + + //Update the textblock's text binding. + BindingExpression expression = textBlock.GetBindingExpression(TextProperty); + if (null != expression) + { + expression.UpdateTarget(); + } + } + } + } + + /// + /// Gets or sets the length of the max. + /// + /// The length of the max. + public int MaxLength + { + get + { + return (int)GetValue(MaxLengthProperty); + } + set + { + SetValue(MaxLengthProperty, value); + } + } + + // Using a DependencyProperty as the backing store for MaxLength. This enables animation, styling, binding, etc... + public static readonly DependencyProperty MaxLengthProperty = + DependencyProperty.Register("MaxLength", typeof(int), typeof(EditableTextBlock), new UIPropertyMetadata(0)); + + private void TextBoxLostFocus(object sender, RoutedEventArgs e) + { + IsInEditMode = false; + } + + /// + /// release the edit mode when user presses enter. + /// + /// The sender. + /// The instance containing the event data. + private void TextBoxKeyUp(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + IsInEditMode = false; + } + } + + /// + /// Invoked when an unhandled  attached event reaches an element in its route that is derived from this class. Implement this method to add class handling for this event. + /// + /// The that contains the event data. This event data reports details about the mouse button that was pressed and the handled state. + protected override void OnMouseDown(MouseButtonEventArgs e) + { + if (e.MiddleButton == MouseButtonState.Pressed) + { + IsInEditMode = true; + } + else if (e.ClickCount == 2) + { + IsInEditMode = true; + } + } + } +} \ No newline at end of file diff --git a/EditTextBlock/EditableTextBlockAdorner.cs b/EditTextBlock/EditableTextBlockAdorner.cs new file mode 100644 index 0000000..3c76bbb --- /dev/null +++ b/EditTextBlock/EditableTextBlockAdorner.cs @@ -0,0 +1,101 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; + +namespace GeekDesk.EditTextBlock +{ + /// + /// Adorner class which shows textbox over the text block when the Edit mode is on. + /// + public class EditableTextBlockAdorner : Adorner + { + private readonly VisualCollection _collection; + + private readonly TextBox _textBox; + + private readonly TextBlock _textBlock; + + public EditableTextBlockAdorner(EditableTextBlock adornedElement) + : base(adornedElement) + { + _collection = new VisualCollection(this); + _textBox = new TextBox(); + _textBlock = adornedElement; + Binding binding = new Binding("Text") { Source = adornedElement }; + _textBox.SetBinding(TextBox.TextProperty, binding); + _textBox.AcceptsReturn = true; + _textBox.MaxLength = adornedElement.MaxLength; + _textBox.KeyUp += _textBox_KeyUp; + _collection.Add(_textBox); + } + + void _textBox_KeyUp(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + _textBox.Text = _textBox.Text.Replace("\r\n", string.Empty); + BindingExpression expression = _textBox.GetBindingExpression(TextBox.TextProperty); + if (null != expression) + { + expression.UpdateSource(); + } + } + } + + protected override Visual GetVisualChild(int index) + { + return _collection[index]; + } + + protected override int VisualChildrenCount + { + get + { + return _collection.Count; + } + } + + protected override Size ArrangeOverride(Size finalSize) + { + _textBox.Arrange(new Rect(0, 0, _textBlock.DesiredSize.Width + 50, _textBlock.DesiredSize.Height * 1.5)); + _textBox.Focus(); + return finalSize; + } + + protected override void OnRender(DrawingContext drawingContext) + { + drawingContext.DrawRectangle(null, new Pen + { + Brush = Brushes.Gold, + Thickness = 2 + }, new Rect(0, 0, _textBlock.DesiredSize.Width + 50, _textBlock.DesiredSize.Height * 1.5)); + } + + public event RoutedEventHandler TextBoxLostFocus + { + add + { + _textBox.LostFocus += value; + } + remove + { + _textBox.LostFocus -= value; + } + } + + public event KeyEventHandler TextBoxKeyUp + { + add + { + _textBox.KeyUp += value; + } + remove + { + _textBox.KeyUp -= value; + } + } + } +} diff --git a/GeekDesk.csproj b/GeekDesk.csproj index bb1fb78..608ad9d 100644 --- a/GeekDesk.csproj +++ b/GeekDesk.csproj @@ -90,6 +90,8 @@ + + @@ -98,10 +100,11 @@ + - + MSBuild:Compile Designer diff --git a/MainWindow.xaml b/MainWindow.xaml index d4b3e84..6441e16 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -4,6 +4,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:GeekDesk" + xmlns:tp="clr-namespace:GeekDesk.EditTextBlock" mc:Ignorable="d" xmlns:util="clr-namespace:GeekDesk.Util" xmlns:DraggAnimatedPanel="clr-namespace:DraggAnimatedPanel" x:Name="window" @@ -11,8 +12,7 @@ Title="MainWindow" Height="500" Width="600"> - + + + + + + + + @@ -127,28 +144,18 @@ Effect="{DynamicResource EffectShadow2}" Margin="5,5,0,5" > - - + - - - + + + @@ -165,7 +172,24 @@ - + + + + @@ -189,7 +213,6 @@ - - + + - - + + diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 5c26a07..cd0c275 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1,9 +1,11 @@ using DraggAnimatedPanelExample; -using GalaSoft.MvvmLight; using GeekDesk.Util; using GeekDesk.ViewModel; using System; +using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; using System.IO; using System.Windows; using System.Windows.Controls; @@ -19,7 +21,8 @@ namespace GeekDesk public partial class MainWindow : Window { - private static AppData appData = CommonCode.GetAppData(); + private AppData appData = CommonCode.GetAppDataByFile(); + private int menuSelectIndexTemp = -1; public MainWindow() { InitializeComponent(); @@ -40,19 +43,20 @@ namespace GeekDesk private void loadData() { this.DataContext = appData; - appData.MenuList.Add("Test1"); + //menus.ItemsSource = appData.MenuList; + appData.MenuList.Add(new MenuInfo() { MenuName = "test1", MenuId = "1", MenuEdit = (int)Visibility.Collapsed }); this.Width = appData.AppConfig.WindowWidth; this.Height = appData.AppConfig.WindowHeight; - List iconList; + ObservableCollection iconList; if (appData.IconMap.ContainsKey("1")) { iconList = appData.IconMap["1"]; } else { - iconList = new List(); + iconList = new ObservableCollection(); appData.IconMap.Add("1", iconList); } icons.ItemsSource = iconList; @@ -89,6 +93,8 @@ namespace GeekDesk } } DelegateCommand _swap2; + + public DelegateCommand SwapCommand2 { get @@ -99,18 +105,22 @@ namespace GeekDesk { int fromS = indexes[0]; int to = indexes[1]; - var elementSource = menus.Items[to]; - var dragged = menus.Items[fromS]; + ObservableCollection menuList = appData.MenuList; + var elementSource = menuList[to]; + var dragged = menuList[fromS]; if (fromS > to) { - menus.Items.Remove(dragged); - menus.Items.Insert(to, dragged); + menuList.Remove(dragged); + menuList.Insert(to, dragged); } else { - menus.Items.Remove(dragged); - menus.Items.Insert(to, dragged); + menuList.Remove(dragged); + menuList.Insert(to, dragged); } + appData.MenuList = menuList; + //menus.Items.Refresh(); + } ); return _swap2; @@ -134,14 +144,14 @@ namespace GeekDesk iconInfo.Path = path; iconInfo.BitmapImage = bi; iconInfo.Name = Path.GetFileNameWithoutExtension(path); - List iconList; + ObservableCollection iconList; if (appData.IconMap.ContainsKey("1")) { iconList = appData.IconMap["1"]; } else { - iconList = new List(); + iconList = new ObservableCollection(); appData.IconMap.Add("1", iconList); } iconList.Add(iconInfo); @@ -231,44 +241,119 @@ namespace GeekDesk } - private void deleteMenu(object sender, RoutedEventArgs e) + /// + /// 删除菜单 + /// + /// + /// + private void DeleteMenu(object sender, RoutedEventArgs e) { - //if (data.SelectedIndex == -1) - //{ - // return; - //} - ViewModel.Menu pojo = (ViewModel.Menu)((ContextMenu)((MenuItem)sender).Parent).DataContext; - string menuTitle = pojo.menu; - int index = 0; - foreach (object obj in menus.Items) - { - string test = ((ViewModel.Menu)obj).menu; - if (test == menuTitle) - { - menus.Items.RemoveAt(index); - menus.Items.Refresh(); - return; - } - index++; - } - + MenuInfo menuInfo = ((MenuItem)sender).Tag as MenuInfo; + appData.MenuList.Remove(menuInfo); + CommonCode.SaveAppData(appData); } + private void StackPanel_MouseMove(object sender, MouseEventArgs e) + { + UIElementCollection childs = ((StackPanel)sender).Children; + IEnumerator iEnumerator = childs.GetEnumerator(); + //((Image)iEnumerator.Current).Style; + } + /// + /// 重命名菜单 将textbox 设置为可见 + /// + /// + /// + private void RenameMenu(object sender, RoutedEventArgs e) + { + MenuInfo menuInfo = ((MenuItem)sender).Tag as MenuInfo; + menuInfo.MenuEdit = (int)Visibility.Visible; + + } + /// + /// 编辑菜单失焦或者敲下Enter键时保存修改后的菜单 + /// + /// + /// + private void LostFocusOrEnterDown(object sender, EventArgs e) + { + TextBox menuBox = null; + if (e.GetType() == typeof(KeyEventArgs)) + { + KeyEventArgs eKey = e as KeyEventArgs; + if (eKey.Key == Key.Enter) + { + menuBox = ((TextBox)sender); + } + } else if(e.GetType() == typeof(RoutedEventArgs)) + { + menuBox = ((TextBox)sender); + } + + if (menuBox != null) + { + MenuInfo menuInfo = menuBox.Tag as MenuInfo; + string text = menuBox.Text; + menuInfo.MenuName = text; + menuInfo.MenuEdit = (int)Visibility.Collapsed; + CommonCode.SaveAppData(appData); + } + } + + /// + /// 当修改菜单元素可见时 设置全选并获得焦点 + /// + /// + /// + private void MenuEditWhenVisibilityChanged(object sender, DependencyPropertyChangedEventArgs e) + { + TextBox box = sender as TextBox; + if (box.Visibility == Visibility.Visible) + { + Keyboard.Focus(box); + box.SelectAll(); + } + } + + /// + /// 当修改菜单元素可见时 设置原菜单为不可见 并且不可选中 + /// 修改菜单元素不可见时 原菜单可见 并 选中 + /// + /// + /// + private void MenuWhenVisibilityChanged(object sender, DependencyPropertyChangedEventArgs e) + { + TextBlock tb = sender as TextBlock; + if (tb.Visibility == Visibility.Collapsed) + { + if (menus.SelectedIndex != -1) + { + menuSelectIndexTemp = menus.SelectedIndex; + menus.SelectedIndex = -1; + } else + { + menus.SelectedIndex = menuSelectIndexTemp; + } + } + } + + /// + /// 新建菜单 + /// + /// + /// + private void CreateMenu(object sender, RoutedEventArgs e) + { + appData.MenuList.Add(new MenuInfo() { MenuEdit = (int)Visibility.Collapsed, MenuId = "zz", MenuName = "NewGouop" }); + menus.SelectedIndex = appData.MenuList.Count - 1; + //appData.MenuList[appData.MenuList.Count - 1].MenuEdit = (int)Visibility.Visible; + CommonCode.SaveAppData(appData); + } } - public class MainModel : ViewModelBase - { - public List MenuList { get; set; } - - public List DataList { get; set; } - - - } - - } diff --git a/Util/CommonCode.cs b/Util/CommonCode.cs index b71d881..5da8c9d 100644 --- a/Util/CommonCode.cs +++ b/Util/CommonCode.cs @@ -15,7 +15,7 @@ namespace GeekDesk.Util /// 获取app 数据 /// /// - public static AppData GetAppData() + public static AppData GetAppDataByFile() { AppData appData; if (!File.Exists(AppConstant.DATA_FILE_PATH)) diff --git a/Util/VisibilityConvert.cs b/Util/VisibilityConvert.cs new file mode 100644 index 0000000..0c5fe2d --- /dev/null +++ b/Util/VisibilityConvert.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; + +namespace GeekDesk.Util +{ + class VisibilityConvert : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + int v = (int)value; + + if (v == (int)Visibility.Visible) + { + return Visibility.Visible; + } else if (v == (int)Visibility.Collapsed) + { + return Visibility.Collapsed; + } + return v; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/ViewModel/AppData.cs b/ViewModel/AppData.cs index 4229674..f9d14b4 100644 --- a/ViewModel/AppData.cs +++ b/ViewModel/AppData.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; namespace GeekDesk.ViewModel @@ -7,11 +8,11 @@ namespace GeekDesk.ViewModel [Serializable] class AppData : INotifyPropertyChanged { - private List menuList = new List(); - private Dictionary> iconMap = new Dictionary>(); + private ObservableCollection menuList = new ObservableCollection(); + private Dictionary> iconMap = new Dictionary>(); private AppConfig appConfig = new AppConfig(); - public List MenuList + public ObservableCollection MenuList { get { @@ -24,7 +25,7 @@ namespace GeekDesk.ViewModel } } - public Dictionary> IconMap + public Dictionary> IconMap { get { diff --git a/ViewModel/IconInfo.cs b/ViewModel/IconInfo.cs index d685f0d..6341a53 100644 --- a/ViewModel/IconInfo.cs +++ b/ViewModel/IconInfo.cs @@ -1,4 +1,5 @@ -using System; +using GeekDesk.Constant; +using System; using System.ComponentModel; using System.IO; using System.Windows.Media.Imaging; @@ -15,6 +16,8 @@ namespace GeekDesk.ViewModel private BitmapImage bitmapImage; //位图 private byte[] imageByteArr; //图片 base64 private string content; //显示信息 + private int imageWidth = (int)DefaultConstant.IMAGE_WIDTH; + private int imageHeight = (int)DefaultConstant.IMAGE_HEIGHT; public int Count { @@ -100,6 +103,19 @@ namespace GeekDesk.ViewModel } } + public int ImageWidth + { + get + { + return imageWidth; + } + set + { + imageWidth = value; + OnPropertyChanged("ImageWidth"); + } + } + [field: NonSerializedAttribute()] diff --git a/ViewModel/MenuInfo.cs b/ViewModel/MenuInfo.cs new file mode 100644 index 0000000..8564f30 --- /dev/null +++ b/ViewModel/MenuInfo.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace GeekDesk.ViewModel +{ + + [Serializable] + class MenuInfo : INotifyPropertyChanged + { + [field: NonSerializedAttribute()] + public event PropertyChangedEventHandler PropertyChanged; + private void OnPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + private string menuName; + private string menuId; + private int menuEdit = (int)Visibility.Collapsed; + private int notMenuEdit = (int)Visibility.Visible; + + public string MenuName + { + get + { + return menuName; + } + set + { + menuName = value; + OnPropertyChanged("MenuName"); + } + } + + public string MenuId + { + get + { + return menuId; + } + set + { + menuId = value; + OnPropertyChanged("MenuId"); + } + } + + public int MenuEdit + { + get + { + return menuEdit; + } + set + { + menuEdit = value; + if (menuEdit == (int)Visibility.Visible) + { + NotMenuEdit = (int)Visibility.Collapsed; + } else + { + NotMenuEdit = (int)Visibility.Visible; + } + OnPropertyChanged("MenuEdit"); + } + } + + public int NotMenuEdit + { + get + { + return notMenuEdit; + } + set + { + notMenuEdit = value; + OnPropertyChanged("NotMenuEdit"); + } + } + } +} diff --git a/ViewModel/MenuViewModel.cs b/ViewModel/MenuViewModel.cs deleted file mode 100644 index 652a67c..0000000 --- a/ViewModel/MenuViewModel.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.ObjectModel; - -namespace GeekDesk.ViewModel -{ - class MenuViewModel - { - - public MenuViewModel() - { - - } - - public ObservableCollection GetMenus() - { - ObservableCollection menus = new ObservableCollection(); - menus.Add(new Menu() { menu = "test1" }); - menus.Add(new Menu() { menu = "test2" }); - menus.Add(new Menu() { menu = "test3" }); - return menus; - } - - - } - - - - public class Menu - { - public string menu { get; set; } - } -}