Ribbon整合Avalondock 2.0实现多文档界面设计(一)

Ribbon整合Avalondock 2.0实现多文档界面设计(一)前些时间研究了WPF的一些框架,感觉基于Prism框架的MVVM模式对系统的UI与逻辑分离很好,所以就按照之前Winform的框架设计,用WPF做了一套,感觉比Winform要强很多。MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点1.低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的”View”上,…

大家好,又见面了,我是你们的朋友全栈君。

前些时间研究了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功能图:

1

现在我做了个实例,整合模仿Office 2010的Ribbon效果:

(1)Blue:

systemUI

(2)Silver

silver2

(3)Black

black

black2

我把框架的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); 
        }

项目解决方案图:

project

现在只稍微提一下,后续有时间再把更详细的设计方法说明。

转载于:https://www.cnblogs.com/happyyftk/p/6904325.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/162130.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 常见数据结构与算法整理总结(下)_常用数据结构与算法

    常见数据结构与算法整理总结(下)_常用数据结构与算法数据结构是以某种形式将数据组织在一起的集合,它不仅存储数据,还支持访问和处理数据的操作。算法是为求解一个问题需要遵循的、被清楚指定的简单指令的集合。下面是自己整理的常用数据结构与算法相关内容,如有错误

  • 用户自定义类加载器下载_spring类加载器顺序

    用户自定义类加载器下载_spring类加载器顺序在Java的日常应用程序开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式。为什么要自定义类加载器?隔离加载类 修改类加载的方式 扩展加载源 防止源码泄漏用户自定义类加载器实现步骤:开发人员可以通过继承抽象类ava.1ang.ClassLoader类的方式,实现自己的类加载器,以满足一些特殊的需求 在JDK1.2之前,在自定义类加载器时,总会去继承ClassLoader类并重写1oadClass()方法,从而实现自定义的类加载类

  • postMessage的使用

    postMessage的使用postMessage是H5的API,用来解决跨页面通信的。postMessage的使用分为发送方和接收方。发送方的代码用法如下:otherWindow.postMessage(message,targetOrigin,[transfer]);otherWindow是接收方的window对象。可以通过以下几种方法获得,例如window.open()方法返回的值就是打开页面的window对象,或…

  • java.lang.abstractMethodError的错误解决「建议收藏」

    java.lang.abstractMethodError的错误解决「建议收藏」日常开发中,如果在打包后遇到过java.lang.abstractMethodError的问题,其中一部分,可能是混淆引起的。解决方法就是把提示报错的地方,通过-keep的方式过滤掉,不让那些代码进行混淆。本人遇到的是一个RecyclerView使用时adapter中的getItemCount方法报错。原因是Adapter是内部类,而getItemCount是公共方法。getItemCo…

  • make命令和makefile文件

    make命令和makefile文件的结合提供了一个在项目管理领域十分强大的工具,它不仅常被用于控制源代码的编译,而且还用于手册页的编写以及将应用程序安装到目标目录。makefile文件由一组依赖关系

    2021年12月28日
  • windbg使用详解_市场配置资源的基础是什么

    windbg使用详解_市场配置资源的基础是什么WinDbg配置和使用基础

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号