基于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层影响. 最后我想到使用 ...
随机推荐
- Django 四——ModelForm用法
内容概要: 1.新增数据库表中数据 2.更新数据库表中数据 Django的ModelForm Django中内置了Form和Model两个类,有时候页面的表单form类与Model类是一一对应,因此分 ...
- 使用html进行浏览器判断,浏览器条件注释
下面来点今天写东西的时候查资料,收集的关于使用html进行浏览器判断的一些资料: 条件注释的基本格式: <!--[if expression]>注释内容<![endif]--> ...
- Careercup - Microsoft面试题 - 5188169901277184
2014-05-12 06:12 题目链接 原题: Write a function to retrieve the number of a occurrences of a substring(ev ...
- Bug的类型
美国计算机科学家.图灵奖获得者詹姆斯·尼古拉·格雷(Jim Gray),在他的著名的论文“Why do computers stop and what can be done about it?”中首 ...
- CentOS 7使用dnf安装Memcached以及启动、停止、开机启动等设置
1.安装Memcached dnf install memcached 根据提示完成安装 2.启动Memcached 输入以下命令: service memcached start 输出以下内容: R ...
- [oldboy-django][2深入django]django模板使用函数
1 模板引入子html--include 模板引擎 - 母版 - include,导入公共的html a. 用法:{% include "pub.html" %}, pub.htm ...
- c++ 中的slipt实现
来自 http://www.cnblogs.com/dfcao/p/cpp-FAQ-split.html http://blog.diveinedu.com/%E4%B8%89%E7%A7%8D%E5 ...
- 【bzoj1266】[AHOI2006]上学路线route 最短路+最小割
题目描述 可可和卡卡家住合肥市的东郊,每天上学他们都要转车多次才能到达市区西端的学校.直到有一天他们两人参加了学校的信息学奥林匹克竞赛小组才发现每天上学的乘车路线不一定是最优的. 可可:“很可能我们在 ...
- windows通过NSF挂载centos目录
windows通过NSF挂载centos目录 来源: http://blog.csdn.net/u012955038/article/details/77151346 CentOS 配置 1.安装NF ...
- [UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机
[UOJ#132][BZOJ4200][luogu_P2304][NOI2015]小园丁与老司机 试题描述 小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面.田野上有 \(n\) 棵许愿 ...