当前位置: 代码迷 >> 综合 >> 在Silverlight 2 Beta2 中实现菜单(Menu)——数据可源自SharePoint
  详细解决方案

在Silverlight 2 Beta2 中实现菜单(Menu)——数据可源自SharePoint

热度:2   发布时间:2024-01-09 23:57:40.0

       近日做了一个在Silverlight 2 beta 2中实现菜单功能的小程序,支持菜单折叠。如图:

                                                 

    菜单的配置信息可以从SharePoint中读取,SharePoint中创建一个List, 各字段如下:

Column Name

Column Type

Title

Text Field

Hyperlink

Hyperlink

TopLevelLink

Binary (Y/N)

Parent Link

Text Field (only available if Top Level Link = N)

 

    在Silverlight程序中有一个MenuConfig.xml文件,用来配置SharePoint地址等相关信息:

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <MenuConfig>
  3.     <ListsServiceUrl>http://localhost/Docs/_vti_bin/Lists.asmx</ListsServiceUrl>
  4.     <MenuListName>MenuList</MenuListName>
  5.     <MenuItemHorizontalSpace>20.0</MenuItemHorizontalSpace>
  6.     <MenuItemVerticalSpace>25.0</MenuItemVerticalSpace>
  7.     <MenuLinkTargetName>_blank</MenuLinkTargetName>
  8. </MenuConfig>

   在Page.xaml.cs页中,首先下载并取得MenuConfig.xml信息(指USING_TEST_DATA = false 时;若为true,则表示不从SharePoint读取配置信息,而直接构造测试数据)

  1.  private const bool USING_TEST_DATA = false;      // True to use dummy test data, and False to use data from sharepoint server.
  2.         private Configuration config = new Configuration();
  3.         private Menu menu;
  4.         public Page()
  5.         {
  6.             InitializeComponent();
  7.             this.Loaded += new RoutedEventHandler(Page_Loaded);
  8.             config.GetConfigurationCompleted += new RoutedEventHandler(config_GetConfigurationCompleted);
  9.         }
  10.         #region Events
  11.         void Page_Loaded(object sender, RoutedEventArgs e)
  12.         {
  13.             if (!USING_TEST_DATA)                       // using datas from SharePoint
  14.                 config.LoadMenuConfig();
  15.             else
  16.                 CreateMenuUsingTestData();              // using test data to create menu
  17.         }
  18.         void config_GetConfigurationCompleted(object sender, RoutedEventArgs e)
  19.         {
  20.             txtWait.Text = "Wait for pull informations from sharepoint...";
  21.             GetMenuDatas();
  22.         }

    接着调用SharePoint的WebService来获取List里的菜单数据(关于调用WebService可能遇到的问题可以查看《Silverlight 2beta2 调用 SharePoint的WebService......》

  1. private void GetMenuDatas()
  2.         {
  3.             BasicHttpBinding bind = new BasicHttpBinding();
  4.             EndpointAddress endpoint = new EndpointAddress(config.ListsServiceUrl);
  5.             SPListService.ListsSoapClient lsc = new MenuControlForSharePoint.SPListService.ListsSoapClient(bind, endpoint);
  6.             lsc.GetListItemsCompleted += new EventHandler<MenuControlForSharePoint.SPListService.GetListItemsCompletedEventArgs>(lsc_GetListItemsCompleted);
  7.             XElement viewFileds = new XElement("ViewFields",
  8.                                                             new XElement("FieldRef"new XAttribute("Name""Title")),
  9.                                                             new XElement("FieldRef"new XAttribute("Name""Hyperlink")),
  10.                                                             new XElement("FieldRef"new XAttribute("Name""TopLevelLink")),
  11.                                                             new XElement("FieldRef"new XAttribute("Name""ParentLink"))
  12.                                               );
  13.             lsc.GetListItemsAsync(config.MenuListName, nullnull, viewFileds, nullnullnull);
  14.         }
  15. void lsc_GetListItemsCompleted(object sender, MenuControlForSharePoint.SPListService.GetListItemsCompletedEventArgs e)
  16.         {
  17.             XDocument doc = XDocument.Parse(e.Result.ToString());
  18.             var lstMenuInfo = from menuInfo in doc.Descendants("{#RowsetSchema}row").ToList()
  19.                               select new MenuInfo
  20.                               {
  21.                                   Title = (string)menuInfo.Attribute("ows_Title"),
  22.                                   Hyperlink = (string)menuInfo.Attribute("ows_Hyperlink"),
  23.                                   TopLevelLink = (int)menuInfo.Attribute("ows_TopLevelLink") == 1,
  24.                                   ParentLink = (string)menuInfo.Attribute("ows_ParentLink"),
  25.                               };
  26.             // render the menu items
  27.             RenderMenu(lstMenuInfo);
  28.         }

    菜单数据获取完毕后就开始绘制菜单

  1.       private void RenderMenu(IEnumerable<MenuInfo> lstMenuInfo)
  2.         {
  3.             // Init menu
  4.             InitMenu(lstMenuInfo);
  5.             //create menu
  6.             menu.Render();
  7.             //exapand all menu items
  8.             menu.ExpandAll();
  9.         }
  10.        private void InitMenu(IEnumerable<MenuInfo> lstMenuInfo)
  11.         {
  12.             menu = new Menu(canMenu);
  13.             menu.MenuItemHorizontalSpace = config.MenuItemHorizontalSpace;
  14.             menu.MenuItemVerticalSpace = config.MenuItemVerticalSpace;
  15.             menu.TargetName = config.MenuLinkTargetName;
  16.             foreach (MenuInfo menuInfo in lstMenuInfo)
  17.             {
  18.                 if (menuInfo.TopLevelLink)
  19.                 {
  20.                     MenuItem mi = GetMenuItem(menuInfo);
  21.                     mi.IndexInCurrentLevel = menu.TopMenuItems.Count;
  22.                     mi.Level = 0;
  23.                     menu.TopMenuItems.Add(mi);
  24.                     AddSumMenu(mi, lstMenuInfo);
  25.                 }
  26.             }
  27.         }
  28.         private void AddSumMenu(MenuItem parentMenu, IEnumerable<MenuInfo> lstMenuInfo)
  29.         {
  30.             foreach (MenuInfo menuInfo in lstMenuInfo)
  31.             {
  32.                 if (!menuInfo.TopLevelLink && menuInfo.ParentLink.Equals(parentMenu.Text))
  33.                 {
  34.                     MenuItem mi = GetMenuItem(menuInfo);
  35.                     mi.IndexInCurrentLevel = parentMenu.Children.Count;
  36.                     mi.Level = parentMenu.Level + 1;
  37.                     mi.ParentMenuItem = parentMenu;
  38.                     parentMenu.Children.Add(mi);
  39.                     AddSumMenu(mi, lstMenuInfo);
  40.                 }
  41.             }
  42.         }
  43.         private MenuItem GetMenuItem(MenuInfo menuInfo)
  44.         {
  45.             string url = "", toolTip = "";
  46.             Uri linkUri = null;
  47.             string text = menuInfo.Title;
  48.             string hyperLink = menuInfo.Hyperlink;
  49.             if (!String.IsNullOrEmpty(hyperLink))
  50.             {
  51.                 string[] arrLink = hyperLink.Split(new Char[] { ','' ' }, StringSplitOptions.RemoveEmptyEntries);
  52.                 if (arrLink.Length > 0)
  53.                 {
  54.                     url = arrLink[0];
  55.                     if (!String.IsNullOrEmpty(url))
  56.                         linkUri = new Uri(url);
  57.                     if (arrLink.Length > 1)
  58.                         toolTip = arrLink[1];
  59.                 }
  60.             }
  61.             return new MenuItem(text, linkUri, toolTip);
  62.         }

       其中private void InitMenu(IEnumerable<MenuInfo> lstMenuInfo) 方法将获取的菜单数据组织成一个有Menu.TopMenuItems负责的树型结构,然后交给Menu类来绘制菜单,并在绘制菜单完毕后将所有的子菜单都展开。

 

      关于Menu类,主要代码如下:

  1. public void Render()
  2.         {
  3.             MenuHolder.Children.Clear();
  4.             foreach (MenuItem mi in TopMenuItems)
  5.             {
  6.                 AddMenuLink(MenuHolder, mi);
  7.                 AddSubMenu(mi); 
  8.             }
  9.         }
  10.         public void ExpandAll()
  11.         {
  12.             foreach (MenuItem mi in TopMenuItems)
  13.                 ExpandMenuAndChildren(mi);
  14.         }
  15.         #endregion
  16.         #region Private Methods
  17.         private void AddSubMenu(MenuItem parentMenu)
  18.         {
  19.             foreach (MenuItem mi in parentMenu.Children)
  20.             {
  21.                 AddMenuLink(parentMenu.ChildrenHolder, mi);
  22.                 AddSubMenu(mi);
  23.             }
  24.         }
  25.         private void AddMenuLink(Panel parentMenuHolder, MenuItem mi)
  26.         {
  27.             MenuLink ml = new MenuLink();
  28.             ml.Text = mi.Text;
  29.             ml.Url = mi.Url;
  30.             ml.ToolTip = mi.ToolTip;
  31.             ml.TargetName = _targetName;
  32.             ml.SetValue(Canvas.TopProperty, mi.IndexInCurrentLevel * _menuItemVerticalSpace);
  33.             ml.MouseLeftButtonUp += new MouseButtonEventHandler(MouseLink_MouseLeftButtonUp);
  34.             Canvas childrenHolder = new Canvas();
  35.             childrenHolder.Visibility = Visibility.Collapsed;
  36.             mi.IsExpanded = false;
  37.             childrenHolder.SetValue(Canvas.LeftProperty, _menuItemHorizontalSpace);
  38.             childrenHolder.SetValue(Canvas.TopProperty, (mi.IndexInCurrentLevel + 1) * _menuItemVerticalSpace);
  39.             mi.MenuLinkControl = ml;
  40.             mi.ChildrenHolder = childrenHolder;
  41.             ml.MenuItem = mi;
  42.             parentMenuHolder.Children.Add(ml);
  43.             parentMenuHolder.Children.Add(childrenHolder);
  44.         }
  45.         private void AdjustBrotherMenuTopProperties(MenuItem mi, double dreich)
  46.         {
  47.             List<MenuItem> brothers;
  48.             if (mi.ParentMenuItem == null)
  49.                 brothers = TopMenuItems;
  50.             else
  51.                 brothers = mi.ParentMenuItem.Children;
  52.             for (int i = mi.IndexInCurrentLevel + 1; i < brothers.Count; i++)
  53.             {
  54.                 MenuLink brogherItem = brothers[i].MenuLinkControl;
  55.                 double brotherItemOldTop = Convert.ToDouble(brogherItem.GetValue(Canvas.TopProperty));
  56.                 brogherItem.SetValue(Canvas.TopProperty, brotherItemOldTop + dreich);
  57.                 Panel brotherHolder = brothers[i].ChildrenHolder;
  58.                 double brotherHolderOldTop = Convert.ToDouble(brotherHolder.GetValue(Canvas.TopProperty));
  59.                 brotherHolder.SetValue(Canvas.TopProperty, brotherHolderOldTop + dreich);
  60.             }
  61.             if (mi.ParentMenuItem != null)
  62.                 AdjustBrotherMenuTopProperties(mi.ParentMenuItem, dreich);
  63.         }
  64.         private double GetChildrenHolderHeight(MenuItem mi)
  65.         {
  66.             double height = 0.0;
  67.             if (mi.IsExpanded)
  68.             {
  69.                 foreach (MenuItem child in mi.Children)
  70.                 {
  71.                     height += _menuItemVerticalSpace;
  72.                     height += GetChildrenHolderHeight(child);
  73.                 }
  74.             }
  75.             return height;
  76.         }
  77.         private void ExpandMenu(MenuItem mi)
  78.         {
  79.             if (mi.Children.Count > 0 && !mi.IsExpanded)
  80.             {
  81.                 mi.IsExpanded = true;
  82.                 mi.ChildrenHolder.Visibility = Visibility.Visible;
  83.                 double dreich = GetChildrenHolderHeight(mi);
  84.                 AdjustBrotherMenuTopProperties(mi, dreich);
  85.             }
  86.         }
  87.         private void ExpandMenuAndChildren(MenuItem menuItem)
  88.         {
  89.             ExpandMenu(menuItem);
  90.             foreach (MenuItem mi in menuItem.Children)
  91.                 ExpandMenuAndChildren(mi);
  92.         }
  93.         private void CollapseMenu(MenuItem mi)
  94.         {
  95.             if (mi.Children.Count > 0 && mi.IsExpanded)
  96.             {
  97.                 double dreich = GetChildrenHolderHeight(mi) * (-1.0);
  98.                 mi.IsExpanded = false;
  99.                 mi.ChildrenHolder.Visibility = Visibility.Collapsed;
  100.                 AdjustBrotherMenuTopProperties(mi, dreich);
  101.             }
  102.         }        
  103.         #endregion
  104.         #region Events
  105.         void MouseLink_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  106.         {
  107.             MenuLink ml = sender as MenuLink;
  108.             MenuItem mi = ml.MenuItem;
  109.             if (mi.IsExpanded)
  110.                 CollapseMenu(mi);
  111.             else
  112.                 ExpandMenu(mi);
  113.             // redirect to the url
  114.             if (mi.Url != null)
  115.                 HtmlPage.Window.Navigate(mi.Url, ml.TargetName);
  116.         }

        AdjustBrotherMenuTopProperties方法用来调整因某一项的子菜单高度改变而影响的本级兄弟菜单的Top位置。

 

        该程序的源代码可以在 这里下载

  相关解决方案