你的位置:首页 > ASP.net教程

[ASP.net教程]WPF 快捷键统一管理


    最近刚刚换了工作,到了新公司的接到第一个项目,是做一个分店零售POS系统。客户对界面要求比较高,所以采用了WPF做为客户端开发技术。在POS系统中,快捷键是比较重要的功能,有很多快捷键在功能是实现上相似,WPF需要在每个页面上配置InputBindings。为了维护、开发便利,对快捷键做统一管理,变得很有必要。现在我来介绍一下实现。

   要做到统一管理,我的想法就是让快捷键变成可配置的,其次,能根据配置自动绑定快捷键及处理句柄。废话不多说直接上代码。

 

1、KeyboardShortcuts 快捷键统一管理的入口

 public class KeyboardShortcuts  {    private const string COFINGFILE = "KeyboardShortcutsRule.Config";    public KeyboardShortcuts()    {      Rules = new List<KeyboardShortcutsRule>();      LoadConfig();    }    public List<KeyboardShortcutsRule> Rules { get; set; }    public void ActiveKeysBindings(Window window)    {      foreach (var item in Rules)      {        if (!item.IgnoreWindow.Contains(window.GetType()))        {          if (item.Effectivity.Count == 0 || item.Effectivity.Contains(window.GetType()))          {            window.InputBindings.Add(new InputBinding(item.Command.GetCommand(), new KeyGestureConverter().ConvertFromString(item.Keys) as KeyGesture)                {                  CommandParameter = window                });          }        }      }    }    private static KeyboardShortcuts current = null;    public static KeyboardShortcuts Current    {      get      {        if (current == null)        {          current = new KeyboardShortcuts();        }        return current;      }    }    public void LoadConfig()    {      try      {        XDocument doc = XDocument.Load(COFINGFILE);        this.Rules = doc.Element("Settings").Elements("KeyboardShortcuts")          .Select(o =>            new KeyboardShortcutsRule()            {              Name = o.Attribute("Name").Value,              IsShowInHelp = o.Attribute("IsShowInHelp") != null ? Convert.ToBoolean(o.Attribute("IsShowInHelp").Value) : true,              Keys = o.Attribute("Keys").Value,              IgnoreWindow = new List<Type>().InitListType(o.Elements("Ignore")),              Effectivity = new List<Type>().InitListType(o.Elements("Effect")),              Command = o.Attribute("Command").Value.InitCommand()            }            ).ToList();      }      catch { }    }    public void SaveConfig()    {      try      {        XDocument doc = new XDocument();        var element = new XElement("Settings");        foreach (var item in Rules)        {          var cmdType = item.Command.GetType();          XElement node = new XElement(            "KeyboardShortcuts",            new XAttribute("Name", item.Name),            new XAttribute("Keys", item.Keys),            new XAttribute("IsShowInHelp", item.IsShowInHelp),            new XAttribute("Command", string.Format("{0}|{1}", cmdType.Assembly.FullName, cmdType.ToString())));          foreach (var childItem in item.IgnoreWindow)          {            XElement ignoreList = new XElement("Ignore", childItem);            node.Add(ignoreList);          }          foreach (var childItem in item.Effectivity)          {            XElement effectList = new XElement("Effect", childItem);            node.Add(effectList);          }          element.Add(node);        }        doc.Add(element);        doc.Save(COFINGFILE);      }      catch { }    }  }

 

2、快捷键配置规则实体

  public class KeyboardShortcutsRule  {    public KeyboardShortcutsRule()    {      IsShowInHelp = true;    }    public string Name { get; set; }    public string Keys { get; set; }    public bool IsShowInHelp { get; set; }    public List<Type> IgnoreWindow { get; set; }    public List<Type> Effectivity { get; set; }    public IKeyboardShortcutsCommand Command { get; set; }  }

 

3、对

public static class LinqExtensions  {    public static List<Type> InitListType(this List<Type> _this, IEnumerable<XElement> ignoreNodes)    {      if (_this == null)        _this = new List<Type>();      foreach (var item in ignoreNodes)      {        _this.Add(Assembly.GetExecutingAssembly().GetType(item.Value));      }      return _this;    }    public static IKeyboardShortcutsCommand InitCommand(this string _this)    {      var results = _this.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);      if (results.Count() == 2)      {        return Assembly.Load(results[0]).CreateInstance(results[1]) as IKeyboardShortcutsCommand;      }      else      {        return Assembly.GetExecutingAssembly().CreateInstance(results[0]) as IKeyboardShortcutsCommand;      }    }  }

 

 

 

4、快捷键处理命令接口【实现这个接口的对象,在绑定快捷键后将被自动激发,PosCommand实现了WPF的ICommand接口】

  public interface IKeyboardShortcutsCommand  {    PosCommand GetCommand();    string Describe { get; set; }  }

 

5、PosCommand实现了WPF的ICommand接口

public class PosCommand : ICommand  {    public PosCommand() { }    public PosCommand(Action func)    {      Processor = func;    }    public PosCommand(Action func, string describe)    {      Processor = func;      Describe = describe;    }    public PosCommand(Action<object> func, string describe)    {      ProcessorForParameter = func;      Describe = describe;    }    public string Describe { get; set; }    public Action Processor { get; set; }    public Action<object> ProcessorForParameter { get; set; }    public bool CanExecute(object parameter)    {      if (Processor != null)        return true;      if (ProcessorForParameter != null)      {        return true;      }      return false;    }    public void Execute(object parameter)    {      if (Processor != null)        Processor();      if (ProcessorForParameter != null)        ProcessorForParameter(parameter);    }    public event EventHandler CanExecuteChanged;  }

 

6、实现快捷键绑定命令

  public class HelpCommand : IKeyboardShortcutsCommand  {    public HelpCommand()    {      Describe = "帮助";    }    public PosCommand GetCommand()    {      return new PosCommand((o) =>      {        Help page = new Help();        page.Show();      }, Describe);    }    public string Describe { get; set; }  }

 

7、配置

<??><Settings> <KeyboardShortcuts Name="Help" Keys="F1" IsShowInHelp="true" Command="Pharos.POS.Retailing.HelpCommand">  <Ignore>Pharos.POS.Retailing.Login</Ignore> </KeyboardShortcuts> <KeyboardShortcuts Name="ExitSystem" Keys="Alt+F4" Command="Pharos.POS.Retailing.ExitSystemCommand">  <Effect>Pharos.POS.Retailing.MainWindow</Effect>  <Effect>Pharos.POS.Retailing.Login</Effect> </KeyboardShortcuts>  <KeyboardShortcuts Name="LockScreen" Keys="Ctrl+D" Command="Pharos.POS.Retailing.LockScreenCommand">  <Effect>Pharos.POS.Retailing.MainWindow</Effect> </KeyboardShortcuts> <KeyboardShortcuts Name="Cannel" Keys="Escape" Command="Pharos.POS.Retailing.CannelCommand"></KeyboardShortcuts></Settings>

 

8、引用,并启用快捷键设置

  public static class WindowExtensions  {    public static void InitPublicSettings(this Window _this)    {      //激活快捷键      KeyboardShortcuts.Current.ActiveKeysBindings(_this);    } }

  public partial class Login : Window  {    public Login()    {      InitializeComponent();      this.InitPublicSettings();    }   }

 

总结,这么做的好处就是让快捷键自定义变得很容易,只需要实现IKeyboardShortcutsCommand,配置规则文档。但是也带来了安全性问题,任何人只要稍微了解这里的机制,就可以利用快捷键的反射机制,注入程序木马等等问题,就算不懂电脑编程的,删除该配置文件也会造成快捷键失效等等问题。