整理导航模块“LeftNav”
首先说一下我想要实现的效果。
我希望在左侧的导航点击了以后右侧的主体部分发声变化。
之前我在LeftNav模块用的控件是ToggleButton并为其制作了样式。本来想的是自己根据ToggleButton作为基础自己在做一个复合控件出来。不过这里做导航的话,ListBox会更加的适合些。ListBox的样式制作和之前的ToggleButton样式制作大同小异,都是一个原则:
各个VisualStateGroup中的视图状态是可以共存的,VisualStateGroup内部的视图状态只能同时出现一个,尽量不要在多个VisualStateGroup同时改变同一个元素的属性。
下来导航模块“LeftNav”需要从外部加载导航配置文件文件"Nav.xml",将其获得的数据解析并于ListBox做数据绑定。要完成上诉的工作就需要引入Services模块,将各个功能分离开、各司其职。
Nav.xml:
<?xml version="1.0" encoding="utf-8" ?> <root> <module showname="Hello Prism" xapname="OperatingTableTestModule" ViewType="OperatingTableTestModule.Views.HelloPrismView, OperatingTableTestModule, Version=1.0.0.0" /> <module showname="欢迎" xapname="OTWelcomeModule" ViewType="OTWelcomeModule.Views.OTWelcomeView, OTWelcomeModule, Version=1.0.0.0" /> <module showname="CGArt" xapname="OTCGArtModule" ViewType="OT.SL.CGArt2010.Style.Issue._31.Views.OTCGArtView, OT.SL.CGArt2010.Style.Issue.31, Version=1.0.0.0" /> <module showname="妄摄写真" xapname="OTMosatsu" ViewType="OTMosatsu.Views.OTMosatsuView, OTMosatsu, Version=1.0.0.0" /> </root>
这里先定义一个导航的实体类,“LdModule”
namespace OTLeftNavModule.Entities { public class LdModule { //显示名称 public string showname { get; set; } //View类别 public string ViewType { get; set; } //Module的名称 public string xapname { get; set; } } }
service获取数据并解析
namespace OTLeftNavModule.Services { public interface ILeftNavService { void RetrievLdModules(Action<IEnumerable<LdModule>> RetrievLdModulesCallBack); } }
namespace OTLeftNavModule.Services { public class LeftNavService : ILeftNavService { #region ILeftNavService Members /// <summary> /// 回调函数,用来介绍返回的LdModule /// </summary> /// <param name="RetrievLdModulesCallBack"></param> public void RetrievLdModules(Action<IEnumerable<LdModule>> RetrievLdModulesCallBack) { var uri = new Uri(HtmlPage.Document.DocumentUri, "Nav.xml"); WebClient wb = new WebClient(); wb.DownloadStringCompleted += (sender, e) => RetrievLdModulesCallBack(BuildLdModules(e)); wb.DownloadStringAsync(uri); } /// <summary> /// 解析XML /// </summary> /// <param name="e"></param> /// <returns></returns> private IEnumerable<LdModule> BuildLdModules(DownloadStringCompletedEventArgs e) { if (e.Error != null) { return new List<LdModule> { new LdModule() { showname = "error", ViewType = "error" } }; } XDocument xmlLdModules = XDocument.Parse(e.Result); var ldmodules = from module in xmlLdModules.Descendants("module") select new LdModule { showname = (string)module.Attribute("showname"), ViewType = (string)module.Attribute("ViewType"), xapname = (string)module.Attribute("xapname") }; return ldmodules; } #endregion } }
将获取的数据赋给Model类用来做数据绑定
namespace OTLeftNavModule.Models { public class LeftNavModel : INotifyPropertyChanged { ILeftNavService leftNavService; public LeftNavModel(ILeftNavService leftNavService) { ldModules = new ObservableCollection<LdModule>(); this.leftNavService = leftNavService; this.leftNavService.RetrievLdModules(OnRetrievLdModulesComplete); } /// <summary> /// 回调函数,为ldModules赋值 /// </summary> /// <param name="newLdModules"></param> private void OnRetrievLdModulesComplete(IEnumerable<LdModule> newLdModules) { this.ldModules.Clear(); foreach (var module in newLdModules) { this.ldModules.Add(module); } } public ObservableCollection<LdModule> ldModules { get; private set; } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion } }
在Xaml里做绑定
<ListBox Background="{x:Null}" x:Name="ListNav" BorderBrush="{x:Null}" ItemsSource="{Binding ldModules}" Foreground="Black" Style="{StaticResource NavListBoxStyle}" BorderThickness="0" ItemContainerStyle="{StaticResource NavListBoxItemStyle}" FontSize="13.333" Cursor="Hand" Margin="0,2,0,0"> <ListBox.ItemTemplate> <DataTemplate><TextBlock Text="{Binding showname}"/></DataTemplate> </ListBox.ItemTemplate> </ListBox>
最后需要替换右侧的主体Module了,我研究了Composite的Module模块、了解了Module生命周期。需要做到替换主体部分的思路就是先从主体区域得到当前Module,将其移除再载入新的Module。这样会比较适合我当前的项目。
void ListNav_SelectionChanged(object sender, SelectionChangedEventArgs e) { LdModule model = ListNav.SelectedItem as LdModule; //获取选中模块View的类型 Type viewType = Type.GetType(model.ViewType, false); //是否增加被加载过 if (viewType != null) { var resolveView = this.container.Resolve(viewType); IRegion mainRegion = this.regionManager.Regions["MainRegion"]; //获取主体当前的View object view = mainRegion.GetView("mainCurrView"); //移除 if (view != null) mainRegion.Remove(view); //载入新的View mainRegion.Add(resolveView, "mainCurrView"); } else { //新加载Module并自动替换当前视图 moduleManager.LoadModule(model.xapname); } }
作者:Nasa 文章出处:我和未来有约会 (http://nasa.cnblogs.com/) 版权声明:本文的版权归作者与博客园共有。转载时须注明本文的详细链接,否则作者将保留追究其法律责任。 |