基于WPF系统框架设计(4)-Ribbon整合Avalondock 2.0实现多文档界面设计(一)
前些时间研究了WPF的一些框架,感觉基于Prism框架的MVVM模式对系统的UI与逻辑分离很好,所以就按照之前Winform的框架设计,用WPF做了一套,感觉比Winform要强很多。
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点
1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2. 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。
4. 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
MVVM功能图:
现在我做了个实例,整合模仿Office 2010的Ribbon效果:
(1)Blue:
(2)Silver
(3)Black
我把框架的View设计和框架设计简单介绍一下。
View的XAML源码:
<!--<Window x:Class="TLAgent.Ribbon.App.Demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid> </Grid>
</Window>-->
<Fluent:RibbonWindow x:Class="TLAgent.Ribbon.App.Demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Fluent="clr-namespace:Fluent;assembly=Fluent"
xmlns:ad="http://schemas.xceed.com/wpf/xaml/avalondock"
xmlns:vm="clr-namespace:TLAgent.Ribbon.App.Demo"
Title="TLAgent.Ribbon.Application" Width="500" Height="250" Background="#FFEBEDF0" x:Name="window" WindowState="Maximized" WindowStartupLocation="CenterScreen" Icon="/TLAgent.Ribbon.App.Demo;component/Images/usergroup.ico"> <Grid x:Name="layoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Fluent:Ribbon Grid.Row="0">
<!--Add QuickAccess-->
<Fluent:Ribbon.QuickAccessItems>
<Fluent:QuickAccessMenuItem Target="{Binding ElementName=ButtonGreen}"/>
<Fluent:QuickAccessMenuItem Target="{Binding ElementName=ButtonGray}"/>
</Fluent:Ribbon.QuickAccessItems>
<!--Add Tabs-->
<Fluent:RibbonTabItem Header="Home" ReduceOrder="(P),(P),(P),(P),(P)">
<Fluent:RibbonGroupBox Header="Add / Remove">
<Fluent:Button Header="Add" Command="{Binding AddFunctionCommand}" Icon="Images\Green.png" LargeIcon="Images\GreenLarge.png" Name="ButtonGreen" />
<Fluent:Button Header="Remove" Command="{Binding OpenCommand}" Icon="Images\Gray.png" LargeIcon="Images\GrayLarge.png" Name="ButtonGray" />
</Fluent:RibbonGroupBox>
<Fluent:RibbonGroupBox Header="Modify">
<Fluent:Button Header="Add" Command="{Binding AddFunctionCommand}" Icon="Images\Green.png" LargeIcon="Images\GreenLarge.png" Name="ButtonGreen1" />
<Fluent:Button Header="Remove" Command="{Binding OpenCommand}" Icon="Images\Gray.png" LargeIcon="Images\GrayLarge.png" Name="ButtonGray1" />
</Fluent:RibbonGroupBox>
</Fluent:RibbonTabItem> <Fluent:RibbonTabItem Header="用户管理" ReduceOrder="(P),(P),(P),(P),(P)">
<Fluent:RibbonGroupBox Header="User Management">
<Fluent:Button Header="New User" Icon="Images\Pink.png" LargeIcon="Images\PinkLarge.png" Name="ButtonAddUser" />
<Fluent:Button Header="Modify User" Icon="Images\Orange.png" LargeIcon="Images\OrangeLarge.png" Name="ButtonModiryUser" />
</Fluent:RibbonGroupBox>
</Fluent:RibbonTabItem>
<!--Backstage Items-->
<Fluent:Ribbon.Menu>
<Fluent:Backstage Background="Gray">
<Fluent:BackstageTabControl>
<Fluent:Button Header="退出系统" Command="{Binding ExitSystemCommand}" Icon="Images\close.png"/>
</Fluent:BackstageTabControl>
</Fluent:Backstage>
</Fluent:Ribbon.Menu> </Fluent:Ribbon> <ad:DockingManager x:Name="dockManager" Grid.Row="1">
<ad:DockingManager.Theme>
<ad:ExpressionBlueTheme/>
</ad:DockingManager.Theme>
<ad:LayoutRoot>
<ad:LayoutPanel Orientation="Vertical">
<ad:LayoutDocumentPane/>
<ad:LayoutAnchorablePane Name="ToolsPane" DockHeight="150">
</ad:LayoutAnchorablePane>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>
<StatusBar VerticalAlignment="Bottom" Height="23" Grid.Row="2" >
<StatusBarItem VerticalContentAlignment="Center">
<TextBlock x:Name="TxtMessage" Foreground="{Binding ForeColor}" FontWeight="Bold" Text="{Binding ExecuteMessage}"/>
</StatusBarItem>
</StatusBar>
</Grid>
<!--<Window.DataContext>
<vm:WorkspaceViewModel />
</Window.DataContext>-->
</Fluent:RibbonWindow>
ViewModel源码:
/************************************************************************ AvalonDock Copyright (C) 2007-2013 Xceed Software Inc. This program is provided to you under the terms of the New BSD
License (BSD) as published at http://avalondock.codeplex.com/license For more features, controls, and fast professional support,
pick up AvalonDock in Extended WPF Toolkit Plus at http://xceed.com/wpf_toolkit Stay informed: follow @datagrid on Twitter or Like facebook.com/datagrids **********************************************************************/ using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;
using System.Windows;
using TLAgent.WPF.Theme;
using Xceed.Wpf.AvalonDock;
using Xceed.Wpf.AvalonDock.Layout; namespace TLAgent.Ribbon.App.Demo
{
class WorkspaceViewModel : NotificationObject
{
public DelegateCommand AddFunctionCommand { get; set; } public DelegateCommand ExitSystemCommand { get; set; } public DelegateCommand OpenCommand { get; set; } private DockingManager _dockingManager; public WorkspaceViewModel()
{
_dockingManager = MainWindow.DockingManager; AddFunctionCommand = new DelegateCommand(this.OnNew); ExitSystemCommand = new DelegateCommand(this.OnExit); OpenCommand = new DelegateCommand(this.OnOpen); } private void OnOpen()
{
//string frameworkPath = string.Format("/Fluent;component/Themes/Office2010/{0}.xaml", ThemeStyle.Silver);//主框架的样式文件
//Application.Current.Resources.MergedDictionaries.Clear();
//设置界面控件的样式
//设置界面框架的样式
//Application.Current.Resources.MergedDictionaries.Add((ResourceDictionary)(Application.LoadComponent(new Uri(frameworkPath, UriKind.RelativeOrAbsolute))));
} private string _executeMessage; public string ExecuteMessage
{
get { return _executeMessage; }
set { _executeMessage = value;
this.RaisePropertyChanged("ExecuteMessage");
}
} private Brush _foreColor; public Brush ForeColor
{
get { return _foreColor; }
set
{
_foreColor = value;
this.RaisePropertyChanged("ForeColor");
}
} private void OnNew()
{
string functionName = "项目管理";
CreateSystemTab(functionName);
ForeColor = new SolidColorBrush(Colors.White); var leftAnchorGroup = _dockingManager.Layout.LeftSide.Children.FirstOrDefault();
if (leftAnchorGroup == null)
{
leftAnchorGroup = new LayoutAnchorGroup();
_dockingManager.Layout.LeftSide.Children.Add(leftAnchorGroup);
} leftAnchorGroup.Children.Add(new LayoutAnchorable() { Title = "New Anchorable" });
ExecuteMessage = "成功新建,Tabs:" + functionName;
} private void CreateSystemTab(string tabName)
{
var firstDocumentPane =_dockingManager.Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
if (firstDocumentPane != null)
{ LayoutDocument doc2 = new LayoutDocument();
AddUserWindow control1 = new AddUserWindow();
doc2.Title = tabName;
doc2.Content = control1;
doc2.IsActive = true;
firstDocumentPane.Children.Add(doc2); }
} private void OnExit()
{
MessageBoxResult result = MessageBox.Show("确定要退出系统吗?", "确认消息", MessageBoxButton.OKCancel, MessageBoxImage.Question);
if (result == MessageBoxResult.OK)
{
Application.Current.Shutdown();
var serializer = new Xceed.Wpf.AvalonDock.Layout.Serialization.XmlLayoutSerializer(_dockingManager);
serializer.Serialize(@".\AvalonDock.config");
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
更换主题:提供统一的接口就可以实现整合框架和控件主题更换。
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : RibbonWindow
{
public static DockingManager DockingManager; public MainWindow()
{
InitializeComponent();
DockingManager = dockManager;
ThemeManager.ChangeTheme(dockManager, ThemeStyle.Black);//更换主题接口
this.DataContext = new WorkspaceViewModel();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
this.Unloaded += new RoutedEventHandler(MainWindow_Unloaded);
}
项目解决方案图:
现在只稍微提一下,后续有时间再把更详细的设计方法说明。
基于WPF系统框架设计(4)-Ribbon整合Avalondock 2.0实现多文档界面设计(一)的更多相关文章
- 基于WPF系统框架设计(5)-Ribbon整合Avalondock 2.0实现多文档界面设计(二)
AvalonDock 是一个.NET库,用于在停靠模式布局(docking)中排列一系列WPF/WinForm控件.最新发布的版本原生支持MVVM框架.Aero Snap特效并具有更好的性能. Ava ...
- 基于WPF系统框架设计(6)-整合MVVM框架(Prism)
应用场景 我们基础的框架已经搭建起来了,现在整合MVVM框架Prism,在ViewModel做一些逻辑处理,真正把界面设计分离出来. 这样方便我们系统开发分工合作,同时提高系统可维护性和灵活性. 具体 ...
- 基于WPF系统框架设计(3)-Fluent Ribbon界面布局
一个系统框架除了功能菜单导航,有系统内容显示区域,系统状态栏. Silver: Blue: Black: 系统界面设计,就不进行技术细节介绍了,主题以框架设计为主,Xaml源码参考: <Flue ...
- 基于WPF系统框架设计(1)-为什么要仿Office2010 Ribbon?
为什么系统框架设计使用Ribbon导航模式? 这得从Office软件的演变说起.微软为什么最后选择使用Ribbon,也许就是很多系统设计要使用Ribbon做功能导航的原因. 你是否还记得曾经使用过的M ...
- 基于WPF系统框架设计(2)-Fluent Ribbon之HelloWorld
Fluent/Ribbon是微软在其最新桌面操作系统Windows 7中使用的图形用户界面. Windows平台的进化,伴随着系统图形界面的重新设计.从Windows XP到Windows Vista ...
- 基于WPF系统框架设计(8)-PasswordBox传值到ViewMode
应用场景 我要做一个系统登录功能,需要传用户名和密码到ViewModel中,可是PasswordBox传值到ViewModel中好像跟TextBox等控件不一样.这里需要用到附加属性. 附加属性:一个 ...
- 基于WPF系统框架设计(7)-TextBox/PasswordBox在ViewModel中支持回车命令
应用场景 我现在做一个系统登录功能,要求在PasswordBox上输完密码后回车,能够响应Enter事件,并执行ViewModel中对应的方法.如果登录成功则隐藏当前窗口显示主窗体,登录失败则焦点返回 ...
- 基于WPF系统框架设计(10)-分页控件设计
背景 最近要求项目组成员开发一个通用的分页组件,要求是这个组件简单易用,通用性,兼容现有框架MVVM模式,可是最后给我提交的成果勉强能够用,却欠少灵活性和框架兼容性. 设计的基本思想 传入数据源,总页 ...
- 基于WPF系统框架设计(9)-多值绑定之IMultiValueConverter
应用场景 我想把View层的一个布局控件和功能按钮传到ViewModel层,达到动态变更布局,同时灵活获取功能按钮的属性,让View和ViewModel完全分离,而不受View层影响. 最后我想到使用 ...
随机推荐
- jar包导入仓库中
mvn install:install-file -Dfile=F:/kaptcha-2.3.jar -DgroupId=com.google.code.kaptcha -DartifactId=ka ...
- Django 五——中间件、缓存、CSRF、信号、Bootstrap(模板)
内容概要: 1.Django的请求生命周期是怎么样的? 2.中间件 3.CSRF补充 4.信号 5.Bootstrap(模板) 1.Django的请求生命周期是怎么样的? (即请求发起到返回都经历了什 ...
- 虚拟机安装教程(linux、centOS)
前提: Windows7系统 64位 VMware-workstation-full-11.0.0-2305329.exe CentOS-6.6-x86_64-bin-DVD1.iso 安装步骤: 看 ...
- 非旋Treap总结 : 快过Splay 好用过传统Treap
非旋$Treap$ 其高级名字叫$Fhq\ Treap$,既然叫$Treap$,它一定满足了$Treap$的性质(虽然可能来看这篇的人一定知道$Treap$,但我还是多说几句:$Fhp\ Treap$ ...
- [错误解决]ubuntu 不在 sudoers 文件中。此事将被报告。
跟据报错判断,ubuntu没有sudo权限,经过查询需要将ubuntu账户加入/etc/sudoers中 先切换到root权限 su 输入密码 修改/etc/sudoers配置 vim /etc/su ...
- Solr安装 win系统
安装之前需查看:https://lucene.apache.org/solr/guide/7_6/solr-system-requirements.html#solr-system-requireme ...
- sun.misc.BASE64Encoder()编码有换行符需要手动去除passwordEncode.replace("\n","");
String passwordEncode = new BASE64Encoder().encodeBuffer(password.getBytes());//sun.misc.BASE64Encod ...
- JDBC 学习笔记(十二)—— DataSource
在 JDBC 的实现过程中,最消耗资源的从来不是执行 SQL 之类的过程,而是获取-释放 数据库连接 Connection 的过程. 之前通过 DriverManager 获得的数据库连接对象,每一个 ...
- AngularJs MVC 详解
为什么在前端也需要MVC 1.代码规模越来越大,切分职责是大势所趋 2.为了复用 3.为了后期维护方便 MVC的目的是为了模块化和复用 前端实现MVC的困难 1.操作DOM必须等整个页面加载完 2.多 ...
- 【bzoj4281】[ONTAK2015]Związek Harcerstwa Bajtockiego 树上倍增+LCA
题目描述 给定一棵有n个点的无根树,相邻的点之间的距离为1,一开始你位于m点.之后你将依次收到k个指令,每个指令包含两个整数d和t,你需要沿着最短路在t步之内(包含t步)走到d点,如果不能走到,则停在 ...