WPF自定义Window样式(1)

6. Generic.xaml

功能:

    WPF是制作界面的同样十分利器。最近当做一个种,用的哪怕是WPF。既然用了WPF了,那么自然的,需要从定义窗体样式。所运用的代码是在网上查到的:初稿链接。

  1. 点名url,支持post或get方式加载数据
  2. 从今定义数据查询条件
  3. 列定义时可以本着数据项进行简要的转换处理。如:数据源[{ “name”:
    “张三”,  “age”: 12, “sex”: 1 }],渲染时愿意把sex的值 1 显示也 男性
  4. 支持多选择
  5. 支撑分页
  6. 点击行时自动选中,多选时,点击checkbox进行选中和收回选中
  7. 能够回来选中项目的值,多选时返回选中值的数组

目录:

一个改动的操作:

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace stonemqy.CustomWindow.Main
{
    /// <summary>
    /// Represents a control with a single piece of content and when that content 
    /// changes performs a transition animation. 
    /// </summary>
    /// <QualityBand>Experimental</QualityBand>
    /// <remarks>The API for this control will change considerably in the future.</remarks>
    [TemplateVisualState(GroupName = PresentationGroup, Name = NormalState)]
    [TemplateVisualState(GroupName = PresentationGroup, Name = DefaultTransitionState)]
    [TemplatePart(Name = PreviousContentPresentationSitePartName, Type = typeof(ContentControl))]
    [TemplatePart(Name = CurrentContentPresentationSitePartName, Type = typeof(ContentControl))]
    public class TransitioningContentControl : ContentControl
    {
        #region Visual state names
        /// <summary>
        /// The name of the group that holds the presentation states.
        /// </summary>
        private const string PresentationGroup = "PresentationStates";

        /// <summary>
        /// The name of the state that represents a normal situation where no
        /// transition is currently being used.
        /// </summary>
        private const string NormalState = "Normal";

        /// <summary>
        /// The name of the state that represents the default transition.
        /// </summary>
        public const string DefaultTransitionState = "DefaultTransition";
        #endregion Visual state names

        #region Template part names
        /// <summary>
        /// The name of the control that will display the previous content.
        /// </summary>
        internal const string PreviousContentPresentationSitePartName = "PreviousContentPresentationSite";

        /// <summary>
        /// The name of the control that will display the current content.
        /// </summary>
        internal const string CurrentContentPresentationSitePartName = "CurrentContentPresentationSite";

        #endregion Template part names

        #region TemplateParts
        /// <summary>
        /// Gets or sets the current content presentation site.
        /// </summary>
        /// <value>The current content presentation site.</value>
        private ContentPresenter CurrentContentPresentationSite { get; set; }

        /// <summary>
        /// Gets or sets the previous content presentation site.
        /// </summary>
        /// <value>The previous content presentation site.</value>
        private ContentPresenter PreviousContentPresentationSite { get; set; }
        #endregion TemplateParts

        #region public bool IsTransitioning

        /// <summary>
        /// Indicates whether the control allows writing IsTransitioning.
        /// </summary>
        private bool _allowIsTransitioningWrite;

        /// <summary>
        /// Gets a value indicating whether this instance is currently performing
        /// a transition.
        /// </summary>
        public bool IsTransitioning
        {
            get { return (bool)GetValue(IsTransitioningProperty); }
            private set
            {
                _allowIsTransitioningWrite = true;
                SetValue(IsTransitioningProperty, value);
                _allowIsTransitioningWrite = false;
            }
        }

        /// <summary>
        /// Identifies the IsTransitioning dependency property.
        /// </summary>
        public static readonly DependencyProperty IsTransitioningProperty =
            DependencyProperty.Register(
                "IsTransitioning",
                typeof(bool),
                typeof(TransitioningContentControl),
                new PropertyMetadata(OnIsTransitioningPropertyChanged));

        /// <summary>
        /// IsTransitioningProperty property changed handler.
        /// </summary>
        /// <param name="d">TransitioningContentControl that changed its IsTransitioning.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnIsTransitioningPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TransitioningContentControl source = (TransitioningContentControl)d;

            if (!source._allowIsTransitioningWrite)
            {
                source.IsTransitioning = (bool)e.OldValue;
                throw new InvalidOperationException("TransitiotioningContentControl_IsTransitioningReadOnly");
            }
        }
        #endregion public bool IsTransitioning

        /// <summary>
        /// The storyboard that is used to transition old and new content.
        /// </summary>
        private Storyboard _currentTransition;

        /// <summary>
        /// Gets or sets the storyboard that is used to transition old and new content.
        /// </summary>
        private Storyboard CurrentTransition
        {
            get { return _currentTransition; }
            set
            {
                // decouple event
                if (_currentTransition != null)
                {
                    _currentTransition.Completed -= OnTransitionCompleted;
                }

                _currentTransition = value;

                if (_currentTransition != null)
                {
                    _currentTransition.Completed += OnTransitionCompleted;
                }
            }
        }

        #region public string Transition
        /// <summary>
        /// Gets or sets the name of the transition to use. These correspond
        /// directly to the VisualStates inside the PresentationStates group.
        /// </summary>
        public string Transition
        {
            get { return GetValue(TransitionProperty) as string; }
            set { SetValue(TransitionProperty, value); }
        }

        /// <summary>
        /// Identifies the Transition dependency property.
        /// </summary>
        public static readonly DependencyProperty TransitionProperty =
            DependencyProperty.Register(
                "Transition",
                typeof(string),
                typeof(TransitioningContentControl),
                new PropertyMetadata(DefaultTransitionState, OnTransitionPropertyChanged));

        /// <summary>
        /// TransitionProperty property changed handler.
        /// </summary>
        /// <param name="d">TransitioningContentControl that changed its Transition.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnTransitionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            TransitioningContentControl source = (TransitioningContentControl)d;
            string oldTransition = e.OldValue as string;
            string newTransition = e.NewValue as string;

            if (source.IsTransitioning)
            {
                source.AbortTransition();
            }

            // find new transition
            Storyboard newStoryboard = source.GetStoryboard(newTransition);

            // unable to find the transition.
            if (newStoryboard == null)
            {
                // could be during initialization of xaml that presentationgroups was not yet defined
                if (VisualStates.TryGetVisualStateGroup(source, PresentationGroup) == null)
                {
                    // will delay check
                    source.CurrentTransition = null;
                }
                else
                {
                    // revert to old value
                    source.SetValue(TransitionProperty, oldTransition);

                    throw new ArgumentException(
                       "TransitioningContentControl_TransitionNotFound");
                }
            }
            else
            {
                source.CurrentTransition = newStoryboard;
            }
        }
        #endregion public string Transition

        #region public bool RestartTransitionOnContentChange
        /// <summary>
        /// Gets or sets a value indicating whether the current transition
        /// will be aborted when setting new content during a transition.
        /// </summary>
        public bool RestartTransitionOnContentChange
        {
            get { return (bool)GetValue(RestartTransitionOnContentChangeProperty); }
            set { SetValue(RestartTransitionOnContentChangeProperty, value); }
        }

        /// <summary>
        /// Identifies the RestartTransitionOnContentChange dependency property.
        /// </summary>
        public static readonly DependencyProperty RestartTransitionOnContentChangeProperty =
            DependencyProperty.Register(
                "RestartTransitionOnContentChange",
                typeof(bool),
                typeof(TransitioningContentControl),
                new PropertyMetadata(false, OnRestartTransitionOnContentChangePropertyChanged));

        /// <summary>
        /// RestartTransitionOnContentChangeProperty property changed handler.
        /// </summary>
        /// <param name="d">TransitioningContentControl that changed its RestartTransitionOnContentChange.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnRestartTransitionOnContentChangePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((TransitioningContentControl)d).OnRestartTransitionOnContentChangeChanged((bool)e.OldValue, (bool)e.NewValue);
        }

        /// <summary>
        /// Called when the RestartTransitionOnContentChangeProperty changes.
        /// </summary>
        /// <param name="oldValue">The old value of RestartTransitionOnContentChange.</param>
        /// <param name="newValue">The new value of RestartTransitionOnContentChange.</param>
        protected virtual void OnRestartTransitionOnContentChangeChanged(bool oldValue, bool newValue)
        {
        }
        #endregion public bool RestartTransitionOnContentChange

        #region Events
        /// <summary>
        /// Occurs when the current transition has completed.
        /// </summary>
        public event RoutedEventHandler TransitionCompleted;
        #endregion Events

        /// <summary>
        /// Initializes a new instance of the <see cref="TransitioningContentControl"/> class.
        /// </summary>
        public TransitioningContentControl()
        {
            DefaultStyleKey = typeof(TransitioningContentControl);
        }

        /// <summary>
        /// Builds the visual tree for the TransitioningContentControl control 
        /// when a new template is applied.
        /// </summary>
        public override void OnApplyTemplate()
        {
            if (IsTransitioning)
            {
                AbortTransition();
            }

            base.OnApplyTemplate();

            PreviousContentPresentationSite = GetTemplateChild(PreviousContentPresentationSitePartName) as ContentPresenter;
            CurrentContentPresentationSite = GetTemplateChild(CurrentContentPresentationSitePartName) as ContentPresenter;

            if (CurrentContentPresentationSite != null)
            {
                CurrentContentPresentationSite.Content = Content;
            }

            // hookup currenttransition
            Storyboard transition = GetStoryboard(Transition);
            CurrentTransition = transition;
            if (transition == null)
            {
                string invalidTransition = Transition;
                // revert to default
                Transition = DefaultTransitionState;

                throw new ArgumentException(
                    "TransitioningContentControl_TransitionNotFound");
            }

            VisualStateManager.GoToState(this, NormalState, false);
            VisualStateManager.GoToState(this, Transition, true);
        }

        /// <summary>
        /// Called when the value of the <see cref="P:System.Windows.Controls.ContentControl.Content"/> property changes.
        /// </summary>
        /// <param name="oldContent">The old value of the <see cref="P:System.Windows.Controls.ContentControl.Content"/> property.</param>
        /// <param name="newContent">The new value of the <see cref="P:System.Windows.Controls.ContentControl.Content"/> property.</param>
        protected override void OnContentChanged(object oldContent, object newContent)
        {
            base.OnContentChanged(oldContent, newContent);

            StartTransition(oldContent, newContent);
        }

        /// <summary>
        /// Starts the transition.
        /// </summary>
        /// <param name="oldContent">The old content.</param>
        /// <param name="newContent">The new content.</param>
        [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "newContent", Justification = "Should be used in the future.")]
        private void StartTransition(object oldContent, object newContent)
        {
            // both presenters must be available, otherwise a transition is useless.
            if (CurrentContentPresentationSite != null && PreviousContentPresentationSite != null)
            {
                CurrentContentPresentationSite.Content = newContent;

                PreviousContentPresentationSite.Content = oldContent;

                // and start a new transition
                if (!IsTransitioning || RestartTransitionOnContentChange)
                {
                    IsTransitioning = true;
                    VisualStateManager.GoToState(this, NormalState, false);
                    VisualStateManager.GoToState(this, Transition, true);
                }
            }
        }

        /// <summary>
        /// Handles the Completed event of the transition storyboard.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void OnTransitionCompleted(object sender, EventArgs e)
        {
            AbortTransition();

            RoutedEventHandler handler = TransitionCompleted;
            if (handler != null)
            {
                handler(this, new RoutedEventArgs());
            }
        }

        /// <summary>
        /// Aborts the transition and releases the previous content.
        /// </summary>
        public void AbortTransition()
        {
            // go to normal state and release our hold on the old content.
            VisualStateManager.GoToState(this, NormalState, false);
            IsTransitioning = false;
            if (PreviousContentPresentationSite != null)
            {
                PreviousContentPresentationSite.Content = null;
            }
        }

        /// <summary>
        /// Attempts to find a storyboard that matches the newTransition name.
        /// </summary>
        /// <param name="newTransition">The new transition.</param>
        /// <returns>A storyboard or null, if no storyboard was found.</returns>
        private Storyboard GetStoryboard(string newTransition)
        {
            VisualStateGroup presentationGroup = VisualStates.TryGetVisualStateGroup(this, PresentationGroup);
            Storyboard newStoryboard = null;
            if (presentationGroup != null)
            {
                newStoryboard = presentationGroup.States
                    .OfType<VisualState>()
                    .Where(state => state.Name == newTransition)
                    .Select(state => state.Storyboard)
                    .FirstOrDefault();
            }
            return newStoryboard;
        }


    }
}
var list = $('#list').GridView({
            'apiUrl': '/Student/List',  // 指定数据请求的URL路径
            'apiType': 'post',  // 请求的方式
            'columns': [    // 要显示的列,title对应表头,column对应数据项的属性名称,width指定列的宽度,func指定绑定时调用的函数名称
                { title: '姓名', column: 'Name', width: 160 },
                { title: '年龄', column: 'Age' },
                { title: '性别', column: 'Sex', width: 100, 'func': 'convertToSex' }
            ],
            'valueColumn': 'StudentId', // data-value 取值的属性名
            'pageSize': 20, // 每页显示的数量
            'isMultiy': false,  // 是否支持多选
            'isTreeView': false,   // 是否支持树形
            'pager': 'pager',   // 指定包含分页的divid,主要是为了能单独控制pager中的一些数据,把pager给拆出来了,后来发现似乎用处不大
            'onRowClick': function(id) { }, // 当数据行被点击时执行的回调,参数是tr中的data-value
            'convertSource': function (data) { return data.body; }, // 使用数据源之前对数据进行转换。因为我的api返回的都是{ code: 200, body: [] }这种类型,需要在这里直接返回body
            'onDataBindComplete': function() {}, // 当数据加载完成,也就是列表渲染完成后的回调。比如说提醒用户加载完成之类的
            'getSearchData': function() { return $('#form1').serialize(); },    // 获取查询参数,这个很重要,想了很多办法,最终采用了这种方案,在查询前运行这个函数,将返回值作为ajax的查询参数
            'listCssClass': 'table',    // 列表table的样式名
            'pagerCssClass': 'pager',   // 分页最外面div的样式名
            'beforeSend': function() { }    // ajax请求之前调用的函数,原本是为了提醒一下加载已开始,请稍后之类的,现在没怎么用到
        });

WPF自定义Window样式(2)

OK,接下去就是者扩展的切实落实了,代码很多,但思路非常简短,主要就是是代码的拼凑。大家好拘留吧!

     
 创建空白项目stonemqy.CustomWindow,添加WPF项目stonemqy.CustomWindow.Main。在stonemqy.CustomWindow.Main中上加文件夹Themes,并在里边添加资源字典Generic.xaml,注意这里的Themes文件夹和Generic.xaml资源字典的讳不可更改。并于列下相继添加类VisualStates、TransitioningContentControl和CustomWindow。

(function ($) {

    $.fn.GridView = function (settings) {
        // 系统变量
        var self = this;
        self.selected = [];
        var pageindex = 1, pageSize = 20;

        if (settings.pageSize && $.isNumeric(settings.pageSize) && settings.pageSize > 0) {
            pageSize = settings.pageSize;
        }

        var rand = Math.floor(Math.random() * 1000);
        var table = $("<table" + (settings.listCssClass ? " class='" + settings.listCssClass + "'" : "") + " id='myList" + rand + "'></table>");

        var colgroup = colgroup2 = "<colgroup>"
        $.each(settings.columns, function (idx, item) {
            colgroup += "<col" + item.width ? " style='width:" + item.width + "px;'" : "" + ">";
            colgroup2 += "<col" + item.width ? " style='width:" + item.width + "px;'" : "" + ">";
        });
        colgroup += "<col style='width:18px;'></col>";
        colgroup += "</colgroup>";
        colgroup2 += "</colgroup>";
        var table = $("<table" + (settings.listCssClass ? " class='" + settings.listCssClass + "'" : "") + " id='myList" + rand + "'></table>");

        var pagerHtml = '<div' + (!settings.pagerCssClass ? '' : ' class="' + settings.pagerCssClass + '"') + '>';
        //var pagerHtml = '';
        pagerHtml += '<a class="disabled" id="first' + rand + '"><i class="fa fa-fast-backward"></i></a>';
        pagerHtml += '<a class="disabled" id="prev' + rand + '"><i class="fa fa-backward"></i></a>';
        pagerHtml += '<div class="pager-index"><b>第</b><input value="1" type="text" maxlength="4" id="index' + rand + '"><b>页</b></div>';
        pagerHtml += '<a class="disabled" id="next' + rand + '"><i class="fa fa-forward"></i></a>';
        pagerHtml += '<a class="disabled" id="last' + rand + '"><i class="fa fa-fast-forward"></i></a>';
        pagerHtml += '<div class="pager-info2"> 共计 0 条记录,';
        pagerHtml += '每页显示 ' + pageSize + ' 条,';
        pagerHtml += '共 1 页,';
        pagerHtml += '用时 0毫秒';
        pagerHtml += "</div></div>";
        var pagerDom = $(pagerHtml);
        var firstButton, prevButton, nextButton, lastButton, currentSpan, pageSizeSpan, totalCountSpan, totalPagesSpan, loadTimeSpan;

        // 临时变量
        var tbody, pager, cbAll, checkboxes, isPager = false, totalPage = 1;

        // 创建table
        self.append(table);

        // 创建thead
        addChildrenToTable();

        // 为tbody赋值
        tbody = $("#tbody" + rand);

        var colCount = settings.columns.length + 2;
        tbody.html("<tr class='empty'><td colspan='" + colCount + "'>等待加载数据...</td></tr>");

        // 创建分页
        if (settings.pager && $("#" + settings.pager)[0]) {
            pager = $("#" + settings.pager);
            isPager = true;
            pager.append(pagerDom);
            setPagerButtonEvent();
        }

        // 创建渲染函数
        self.fun = new Function("data", renderFunString());

        // 渲染第一列
        self.setFirstCol = function (val) {
            if (settings.isMulti) {
                return "<td class='chk'><input type='checkbox' id='cb" + val + "' value='" + val + "'></td>"
            } else {
                return "<td class='no'>" + val + "</td>";
            }
        }

        // 渲染最后一列
        self.setLastCol = function () {
            return "<td></td>";
        }

        // 渲染中间列
        self.setCol = function (content, width, cssClass, level) {
            var html = "<td";
            html += width ? " style='width:" + width + "px'" : "";
            html += cssClass && cssClass != 'undefined' ? " class='" + cssClass + "'" : "";
            html += ">";
            if (settings.isTreeView) {
                html += level ? "" + (level > 0 ? "|—" : "") + "" : "";
            }
            html += content && content != "undefined" ? content : "";
            html += "</td>";
            return html;
        }

        // 显示指定页码的数据
        self.show = function (index, type) {
            self.selected = [];
            if (!settings.apiUrl) {
                return;
            }

            if (!type || type.toLowerCase() != "post") {
                $.get(settings.apiUrl, getAjaxData(), function (data) {
                    var source = [];
                    if (settings.convertSource && $.isFunction(settings.convertSource)) {
                        source = settings.convertSource(data);
                    } else {
                        source = data;
                    }
                    addRowsToTbody(source);
                });
            } else {
                $.post(settings.apiUrl, getAjaxData(), function (data) {
                    var source = [];
                    if (settings.convertSource && $.isFunction(settings.convertSource)) {
                        source = settings.convertSource(data);
                    } else {
                        source = data;
                    }
                    addRowsToTbody(source);
                });
            }
        };

        // 获取选中的ID
        self.getSelectedId = function () {
            if (self.selected.length == 0) {
                return null;
            } else {
                return self.selected[0];
            }
        };

        self.getSelectedIds = function () {
            return self.selected;
        };

        self.clear = function () {
            self.selected = [];
            $("tr", "#myList" + rand).removeClass("selected");
            $(":checkbox", "#myList" + rand).prop("checked", false);
        };

        // 为table内的元素绑定事件
        tbody.on("click", "tr", function () {
            if ($(this).hasClass("empty")) return;
            $("tr", tbody).removeClass("selected").find(":checkbox").prop("checked", false);
            $(this).addClass("selected").find(":checkbox").prop("checked", true);
            $("#cbAll" + rand).prop("checked", false);
            self.selected = [$(this).data("value")];
        });

        // 绑定复选框点击事件
        if (settings.isMulti) {
            cbAll = $("#cbAll" + rand);

            cbAll.on("click", function () {
                if (!checkboxes) checkboxes = $(":checkbox", tbody);

                if ($(this).prop("checked")) {
                    self.selected = [];

                    $.each(checkboxes, function (idx, item) {
                        $(this).prop("checked", true);
                        self.selected.push($(this).val());

                        var tr = $("#tr" + $(item).val());
                        if (!tr.hasClass("selected")) tr.addClass("selected");
                    });
                } else {
                    checkboxes.prop("checked", false);
                    $("tr", tbody).removeClass("selected");
                    self.selected = [];
                }
            });

            tbody.on("click", ":checkbox", function (event) {
                event.stopPropagation();

                if ($(this).prop("checked")) {
                    $("#tr" + $(this).val()).addClass("selected");
                } else {
                    $("#tr" + $(this).val()).removeClass("selected");
                }
                if (!checkboxes) {
                    checkboxes = $(":checkbox", tbody);
                }

                self.selected = [];

                var unCheckedCount = 0;

                $.each(checkboxes, function () {
                    if ($(this).prop("checked")) {
                        self.selected.push($(this).val());
                    } else {
                        unCheckedCount++;
                    }
                });

                if (unCheckedCount > 0) {
                    cbAll.prop("checked", false);
                } else {
                    cbAll.prop("checked", true);
                }
            });
        }

        // 返回渲染函数的程序体
        function renderFunString() {
            var funString = "var self = this; var html = ''; $.each(data, function(idx, item) { var val = ";
            funString += (settings.valueColumn ? "item." + settings.valueColumn : "idx");
            funString += "; html += '<tr id=\"tr' + val + '\" data-value=\"' + val + '\">'; html += self.setFirstCol(val);";
            var level = null;
            if (settings.levelColumn) {
                level = settings.levelColumn;
            }
            $.each(settings.columns, function (idx, item) {
                if (item.func) {
                    funString += " html += self.setCol( " + item.func + "(item), " + item.width + ", '" + item.cssClass + "'" + (level ? " , item." + level : "") + " );";
                } else {
                    funString += " html += self.setCol( item." + item.column + ", " + item.width + ", '" + item.cssClass + "'" + (level ? " , item." + level : "") + " );";
                }
            });
            funString += " html += self.setLastCol(); html += '</tr>'; idx++; }); return html;";
            return funString;
        }

        // 将数据生成html,并插入到tbody中
        function addRowsToTbody(data) {
            if (data && data.body && data.body.length > 0) {
                var html = self.fun(data.body);
                tbody.html(html);

                if (isPager) {
                    setPagerButton(pageSize, pageindex, data.totalCount, new Date().getTime());
                }
            } else {
                var colCount = settings.columns.length + 2;
                tbody.html("<tr class='empty'><td colspan='" + colCount + "'>请求的数据为空</td></tr>");
            }
        }

        // 创建table
        function addChildrenToTable() {
            var body = "<thead>"
            if (settings.columns) {
                if (settings.isMulti) {
                    body += "<th class='chk'><input type='checkbox' id='cbAll" + rand + "' /></th>";
                } else {
                    body += "<th class='no'></th>";
                }

                $.each(settings.columns, function (idx, col) {
                    body += "<th>" + col.title + "</th>";
                });
                body += "<th></th>";
                body += "</thead><tbody id='tbody" + rand + "'></tbody>";

                table.append($(body));
            }
        }

        // 绑定分页按钮的点击事件
        function setPagerButtonEvent() {
            firstButton = $("#first" + rand);
            prevButton = $("#prev" + rand);
            nextButton = $("#next" + rand);
            lastButton = $("#last" + rand);
            currentSpan = $("#index" + rand);

            pageSizeSpan = $("#size" + rand);;
            totalCountSpan = $("#total" + rand);;
            totalPagesSpan = $("#page" + rand);;
            loadTimeSpan = $("#time" + rand);;

            firstButton.on("click", function () {
                if (!$(this).hasClass("disabled")) {
                    pageindex = 1;
                    self.show();
                }
            });

            prevButton.on("click", function () {
                if (!$(this).hasClass("disabled")) {
                    pageindex -= 1;
                    pageindex = pageindex <= 0 ? 1 : pageindex;
                    self.show();
                }
            });

            nextButton.on("click", function () {
                if (!$(this).hasClass("disabled")) {
                    pageindex += 1;
                    self.show();
                }
            });

            lastButton.on("click", function () {
                if (!$(this).hasClass("disabled")) {
                    pageindex = totalPage;
                    self.show();
                }
            });

            currentSpan.on("change", function () {
                var nc = Number($(this).val());
                if (nc && nc <= totalPage && nc > 0) {
                    pageindex = nc;
                    self.show();
                } else {
                    $(this).val(pageindex);
                }
            });
        }

        // 配置 Pager 按钮
        function setPagerButton(size, index, total, start) {
            if (total == 0) {
                pager.hide();
            } else {
                pager.show();
            }

            // 总页数
            var pages = Math.ceil(total / size);
            pages = (pages == 0 ? 1 : pages);
            totalPage = pages;

            if (pages == 1) {
                if (!firstButton.hasClass("disabled")) {
                    firstButton.addClass("disabled");
                }
                if (!prevButton.hasClass("disabled")) {
                    prevButton.addClass("disabled");
                }
                if (!nextButton.hasClass("disabled")) {
                    nextButton.addClass("disabled");
                }
                if (!lastButton.hasClass("disabled")) {
                    lastButton.addClass("disabled");
                }
            } else {
                if (index == 1) {
                    if (!firstButton.hasClass("disabled")) {
                        firstButton.addClass("disabled");
                    }
                    if (!prevButton.hasClass("disabled")) {
                        prevButton.addClass("disabled");
                    }
                } else {
                    if (firstButton.hasClass("disabled")) {
                        firstButton.removeClass("disabled");
                    }
                    if (prevButton.hasClass("disabled")) {
                        prevButton.removeClass("disabled");
                    }
                }
                currentSpan.val(index);
                if (index == pages) {
                    if (!nextButton.hasClass("disabled")) {
                        nextButton.addClass("disabled");
                    }
                    if (!lastButton.hasClass("disabled")) {
                        lastButton.addClass("disabled");
                    }
                } else {
                    if (nextButton.hasClass("disabled")) {
                        nextButton.removeClass("disabled");
                    }
                    if (lastButton.hasClass("disabled")) {
                        lastButton.removeClass("disabled");
                    }
                }
            }
            totalCountSpan.text(total);
            pageSizeSpan.text(this.pageSize);
            totalPagesSpan.text(pages);
            loadTimeSpan.text((new Date().getTime() - start));
        }

        // 获取ajax的查询参数
        function getAjaxData() {
            var param;
            if ($.isFunction(settings.getSearchData)) {
                param = settings.getSearchData();
            }
            if (isPager) {
                if ($.isArray(param)) {                                             // $("form").serializationArray()
                    param.push({ "name": "pageSize", "value": pageSize });
                    param.push({ "name": "pageIndex", "value": pageindex });
                } else if ($.isPlainObject(param)) {                                 // 自定义查询对象
                    $.extend(true, param, { "pageSize": pageSize, "pageIndex": pageindex });
                } else {                                                             // $("form").serialization()
                    param = (param ? param + "&" : "") + "pageSize=" + pageSize + "&pageIndex=" + pageindex;
                }
            }
            return !!param ? param : {};
        }

        return self;
    }

})(jQuery);

/*
 *使用范例:
 *==========================数据格式============================
 {
  "code": 200,
  "describe": "",
  "totalCount": 3,
  "body": [
    {
      "no": 1,
      "name": "王五",
      "family": {
        "father": "王老五",
        "mother": "陈静蓉"
      }
    },
    {
      "no": 2,
      "name": "张三",
      "family": {
        "father": "张作霖",
        "mother": "李培芳"
      }
    },
    {
      "no": 3,
      "name": "李四",
      "family": {
        "father": "李宗仁",
        "mother": "江少芬"
      }
    }
  ]
 }

 *==========================页面调用============================
    <script src="jquery-1.10.2.js"></script>
    <script src="myGrid.js"></script>
    <script>
        var list = $("#list").myGrid({
            apiUrl: "data.json",
            isMulti: false,
            isTree: true,
            cols: [
                { col: "no", width: 120, title: "编号", cssClass: "chk", level: 0 },
                { col: "name", width: 120, title: "姓名", level: 0 },
                { col: "family.father", width: 120, title: "父亲", level: 1, func: "addFix" }
            ],
            valueCol: "no",
            pager: "pager",
            pageSize: 2,
            cssClass: "default-list-table",
            convertSource: function(data) {
                return data;
            }
        });

        // 这个是用来转换数据的方法
        function addFix(obj) {
            return "000" + obj;
        }
        list.show();
    </script>
  1. MainWindow.xaml

         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:stonemqy.CustomWindow.Main"
         Title="MainWindow" Height="350" Width="525">
     <Grid>
    
     </Grid>
    

    /local:CustomWindow

  2. MainWindow.cs

    namespace stonemqy.CustomWindow.Main
    {

     /// <summary>
     /// MainWindow.xaml 的交互逻辑
     /// </summary>
     public partial class MainWindow : CustomWindow
     {
         public MainWindow()
         {
             InitializeComponent();
         }
     }
    

    }

  3. 运作效果

WPF自定义Window样式(1)

尚无图无精神,先来只截图看看:

2. 创办项目

因个人的习惯与对职能的解说,定义了如此一个setting:

 5. CustomWindow

接触mvc不久,突然没了viewstate和劳务端控件处处都看不顺手,很多以webform时无必要考虑的题材还出现于面前,这之中分页时查询条件保障的题材而是太给自身头疼的事体,权衡再三,决定用ajax局部刷新列表的方来化解此问题。网上基于jquery的grid组件很多,jquerygrid,jqgrid等等,分别试用了瞬间,功能确实挺强,但感到上出接触又,配置起极其多,用起仍觉得束手束脚,所以想来想去,还是用极愚蠢的办法自己举行了一个零件,很简陋,唯一的便宜虽活,容易改及决定。

   
 此处原来关于于CustomWindow的一部分诠释,但是经验证,注释有误,故贴代码时以注释删除了。

using System; 
using System.Windows; 
using System.Windows.Input; 

namespace stonemqy.CustomWindow.Main
{
    public class CustomWindow : Window
    {
        public CustomWindow()
        {
            DefaultStyleKey = typeof(CustomWindow);
            CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, CloseWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, MaximizeWindow, CanResizeWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, MinimizeWindow, CanMinimizeWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, RestoreWindow, CanResizeWindow));
            CommandBindings.Add(new CommandBinding(SystemCommands.ShowSystemMenuCommand, ShowSystemMenu));
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
            if (e.ButtonState == MouseButtonState.Pressed)
                DragMove();
        }

        protected override void OnContentRendered(EventArgs e)
        {
            base.OnContentRendered(e);
            if (SizeToContent == SizeToContent.WidthAndHeight)
                InvalidateMeasure();
        }

        #region Window Commands

        private void CanResizeWindow(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = ResizeMode == ResizeMode.CanResize || ResizeMode == ResizeMode.CanResizeWithGrip;
        }

        private void CanMinimizeWindow(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = ResizeMode != ResizeMode.NoResize;
        }

        private void CloseWindow(object sender, ExecutedRoutedEventArgs e)
        {
            this.Close();
            //SystemCommands.CloseWindow(this);
        }

        private void MaximizeWindow(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.MaximizeWindow(this);
        }

        private void MinimizeWindow(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.MinimizeWindow(this);
        }

        private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
        {
            SystemCommands.RestoreWindow(this);
        }


        private void ShowSystemMenu(object sender, ExecutedRoutedEventArgs e)
        {
            var element = e.OriginalSource as FrameworkElement;
            if (element == null)
                return;

            var point = WindowState == WindowState.Maximized ? new Point(0, element.ActualHeight)
                : new Point(Left + BorderThickness.Left, element.ActualHeight + Top + BorderThickness.Top);
            point = element.TransformToAncestor(this).Transform(point);
            SystemCommands.ShowSystemMenu(this, point);
        }

        #endregion
    }
}

     
首先上原始源码。

3. VisualStates

4. TransitioningContentControl

源码

 

1. 引言

  1. 路代码

 

using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Media;

namespace stonemqy.CustomWindow.Main
{
    public static class VisualStates
    {  /// <summary>
        /// This method tries to get the named VisualStateGroup for the 
        /// dependency object. The provided object's ImplementationRoot will be 
        /// looked up in this call.
        /// </summary>
        /// <param name="dependencyObject">The dependency object.</param>
        /// <param name="groupName">The visual state group's name.</param>
        /// <returns>Returns null or the VisualStateGroup object.</returns>
        public static VisualStateGroup TryGetVisualStateGroup(DependencyObject dependencyObject, string groupName)
        {
            FrameworkElement root = GetImplementationRoot(dependencyObject);
            if (root == null)
            {
                return null;
            }

            return VisualStateManager.GetVisualStateGroups(root)
                .OfType<VisualStateGroup>()
                .Where(group => string.CompareOrdinal(groupName, group.Name) == 0)
                .FirstOrDefault();
        }

        /// <summary>
        /// Gets the implementation root of the Control.
        /// </summary>
        /// <param name="dependencyObject">The DependencyObject.</param>
        /// <remarks>
        /// Implements Silverlight's corresponding internal property on Control.
        /// </remarks>
        /// <returns>Returns the implementation root or null.</returns>
        public static FrameworkElement GetImplementationRoot(DependencyObject dependencyObject)
        {
            Debug.Assert(dependencyObject != null, "DependencyObject should not be null.");
            return (1 == VisualTreeHelper.GetChildrenCount(dependencyObject)) ?
                VisualTreeHelper.GetChild(dependencyObject, 0) as FrameworkElement :
                null;
        }
    }
}
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:stonemqy.CustomWindow.Main"
                    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">


    <DataTemplate x:Key="RestoreWhite">
        <Grid UseLayoutRounding="True"
              RenderTransform="1,0,0,1,.5,.5">
            <Path Data="M2,0 L8,0 L8,6 M0,3 L6,3 M0,2 L6,2 L6,8 L0,8 Z"
                  Width="8"
                  Height="8"
                  VerticalAlignment="Center"
                  HorizontalAlignment="Center"
                  Stroke="White"
                  StrokeThickness="1" />
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="CloseWhite">
        <Grid Margin="1,0,0,0">

            <Rectangle Stroke="White"
                       Height="2"
                       RenderTransformOrigin="0.5,0.5"
                       Width="11"
                       UseLayoutRounding="True">
                <Rectangle.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform />
                        <SkewTransform />
                        <RotateTransform Angle="45" />
                        <TranslateTransform />
                    </TransformGroup>
                </Rectangle.RenderTransform>
            </Rectangle>
            <Rectangle Stroke="White"
                       Height="2"
                       RenderTransformOrigin="0.5,0.5"
                       Width="11"
                       UseLayoutRounding="True">
                <Rectangle.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform />
                        <SkewTransform />
                        <RotateTransform Angle="-45" />
                        <TranslateTransform />
                    </TransformGroup>
                </Rectangle.RenderTransform>
            </Rectangle>
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="MaximizeWhite">
        <Grid>
            <Path Data="M0,1 L9,1 L9,8 L0,8 Z"
                  Width="9"
                  Height="8"
                  Margin="0,2,0,0"
                  VerticalAlignment="Center"
                  HorizontalAlignment="Center"
                  Stroke="White"
                  StrokeThickness="2" />
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="MinimizeWhite">
        <Grid>
            <Path Data="M0,6 L8,6 Z"
                  Width="8"
                  Height="7"
                  VerticalAlignment="Center"
                  HorizontalAlignment="Center"
                  Stroke="White"
                  StrokeThickness="2" />
        </Grid>
    </DataTemplate>



    <Style x:Key="TitleBarButtonFocusVisual">
        <Setter Property="Control.Template">
            <Setter.Value>
                <ControlTemplate>
                    <Rectangle Margin="2"
                               SnapsToDevicePixels="True"
                               Stroke="Transparent"
                               StrokeDashArray="1 2"
                               StrokeThickness="1" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="TitleBarButtonStyle"
           TargetType="{x:Type Button}">
        <Setter Property="Focusable"
                Value="False" />
        <Setter Property="Background"
                Value="Transparent" />
        <Setter Property="BorderBrush"
                Value="Transparent" />
        <Setter Property="BorderThickness"
                Value="1" />
        <Setter Property="HorizontalContentAlignment"
                Value="Center" />
        <Setter Property="VerticalContentAlignment"
                Value="Center" />
        <Setter Property="Padding"
                Value="1" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid x:Name="LayoutRoot">
                        <Rectangle x:Name="ButtonBackground"
                                   Width="28"
                                   Height="28"
                                   Fill="#FFFFFFFF"
                                   Opacity="0" />
                        <Border x:Name="ButtonBorder"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}"
                                SnapsToDevicePixels="true">
                            <ContentPresenter x:Name="TitleBarButtonContentPresenter"
                                              Focusable="False"
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                              Margin="{TemplateBinding Padding}"
                                              RecognizesAccessKey="True"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                        </Border>
                    </Grid>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter Property="Opacity"
                                    Value="0.2"
                                    TargetName="ButtonBackground" />
                        </Trigger>
                        <Trigger Property="IsPressed"
                                 Value="True">
                            <Setter Property="Opacity"
                                    Value="0.4"
                                    TargetName="ButtonBackground" />
                        </Trigger>
                        <Trigger Property="IsEnabled"
                                 Value="false">
                            <Setter TargetName="TitleBarButtonContentPresenter"
                                    Property="Opacity"
                                    Value=".5" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <!--<Style TargetType="{x:Type local:OmecWindow}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:OmecWindow}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>-->



    <Style TargetType="{x:Type local:CustomWindow}">
        <Setter Property="Foreground"
                Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
        <Setter Property="Background"
                Value="#FFF1F1F1" />
        <Setter Property="BorderBrush"
                Value="#FF0874AA" />
        <Setter Property="BorderThickness"
                Value="1" />
        <Setter Property="IsTabStop"
                Value="False" />
        <Setter Property="ResizeMode"
                Value="CanResizeWithGrip" />
        <Setter Property="UseLayoutRounding"
                Value="True" />
        <Setter Property="TextOptions.TextFormattingMode"
                Value="Display" />
        <Setter Property="WindowStyle"
                Value="SingleBorderWindow" />
        <Setter Property="FontFamily"
                Value="Segoe UI" />
        <Setter Property="WindowChrome.WindowChrome">
            <Setter.Value>
                <WindowChrome CornerRadius="0"
                              GlassFrameThickness="1"
                              UseAeroCaptionButtons="False"
                              NonClientFrameEdges="None" />
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomWindow}">


                    <Border BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            x:Name="WindowBorder">
                        <Grid x:Name="LayoutRoot"
                              Background="{TemplateBinding Background}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>

                            <Grid x:Name="PART_WindowTitleGrid"
                                  Grid.Row="0"
                                  Height="26.4"
                                  Background="{TemplateBinding BorderBrush}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <StackPanel Orientation="Horizontal">
                                    <!--<Image Source="{TemplateBinding Icon}"
                                           Margin="7,0,5,0"
                                           VerticalAlignment="Center"
                                          />-->
                                    <Button VerticalAlignment="Center"
                                            Margin="7,0,5,0"
                                            Content="{TemplateBinding Icon}"
                                            Height="{x:Static SystemParameters.SmallIconHeight}"
                                            Width="{x:Static SystemParameters.SmallIconWidth}"
                                            WindowChrome.IsHitTestVisibleInChrome="True"
                                            IsTabStop="False">
                                        <Button.Template>
                                            <ControlTemplate TargetType="{x:Type Button}">
                                                <Image Source="{TemplateBinding Content}" />
                                            </ControlTemplate>
                                        </Button.Template>
                                        <i:Interaction.Triggers>
                                            <i:EventTrigger EventName="Click">
                                                <i:InvokeCommandAction Command="{x:Static SystemCommands.ShowSystemMenuCommand}" />
                                            </i:EventTrigger>
                                            <i:EventTrigger EventName="MouseDoubleClick">
                                                <i:InvokeCommandAction Command="{x:Static SystemCommands.CloseWindowCommand}" />
                                            </i:EventTrigger>
                                        </i:Interaction.Triggers>
                                    </Button>
                                    <ContentControl IsTabStop="False"
                                                    Foreground="White"
                                                    HorizontalAlignment="Center"
                                                    VerticalAlignment="Center"
                                                    FontSize="{DynamicResource {x:Static SystemFonts.CaptionFontSize}}"
                                                    Content="{TemplateBinding Title}" />
                                </StackPanel>
                                <StackPanel x:Name="WindowCommandButtonsStackPanel"
                                            Grid.Column="1"
                                            HorizontalAlignment="Right"
                                            VerticalAlignment="Top"
                                            Background="Transparent"
                                            Orientation="Horizontal"
                                            WindowChrome.IsHitTestVisibleInChrome="True">
                                    <Button x:Name="Minimize"
                                            ToolTip="Minimize"
                                            WindowChrome.IsHitTestVisibleInChrome="True"
                                            Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}"
                                            ContentTemplate="{StaticResource MinimizeWhite}"
                                            Style="{StaticResource TitleBarButtonStyle}"
                                            IsTabStop="False" />
                                    <Grid Margin="1,0,1,0">
                                        <Button x:Name="Restore"
                                                ToolTip="Restore"
                                                WindowChrome.IsHitTestVisibleInChrome="True"
                                                Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}"
                                                ContentTemplate="{StaticResource RestoreWhite}"
                                                Style="{StaticResource TitleBarButtonStyle}"
                                                Visibility="Collapsed"
                                                IsTabStop="False" />
                                        <Button x:Name="Maximize"
                                                ToolTip="Maximize"
                                                WindowChrome.IsHitTestVisibleInChrome="True"
                                                Command="{Binding Source={x:Static SystemCommands.MaximizeWindowCommand}}"
                                                ContentTemplate="{StaticResource MaximizeWhite}"
                                                Style="{StaticResource TitleBarButtonStyle}"
                                                IsTabStop="False" />
                                    </Grid>
                                    <Button x:Name="Close"
                                            ToolTip="Close"
                                            WindowChrome.IsHitTestVisibleInChrome="True"
                                            Command="{Binding Source={x:Static SystemCommands.CloseWindowCommand}}"
                                            ContentTemplate="{StaticResource CloseWhite}"
                                            Style="{StaticResource TitleBarButtonStyle}"
                                            IsTabStop="False" />
                                </StackPanel>
                            </Grid>
                            <AdornerDecorator Grid.Row="1" KeyboardNavigation.IsTabStop="False">
                                <!--<ContentPresenter x:Name="MainContentPresenter"
                                                  KeyboardNavigation.TabNavigation="Cycle" />-->
                                <local:TransitioningContentControl Content="{TemplateBinding Content}"
                                                                   x:Name="MainContentPresenter"

                                                                   KeyboardNavigation.TabNavigation="Cycle" />
                            </AdornerDecorator>
                            <ResizeGrip x:Name="ResizeGrip"
                                        HorizontalAlignment="Right"
                                        VerticalAlignment="Bottom"
                                        Grid.Row="1"
                                        IsTabStop="False"
                                        Visibility="Hidden"
                                        WindowChrome.ResizeGripDirection="BottomRight" />
                        </Grid>
                    </Border>


                    <ControlTemplate.Triggers>
                        <Trigger Property="IsActive"
                                 Value="False">
                            <Setter Property="BorderBrush"
                                    Value="#FF6F7785" />
                        </Trigger>
                        <Trigger Property="WindowState"
                                 Value="Maximized">
                            <Setter TargetName="Maximize"
                                    Property="Visibility"
                                    Value="Collapsed" />
                            <Setter TargetName="Restore"
                                    Property="Visibility"
                                    Value="Visible" />
                            <Setter TargetName="LayoutRoot"
                                    Property="Margin"
                                    Value="7" />
                        </Trigger>
                        <Trigger Property="WindowState"
                                 Value="Normal">
                            <Setter TargetName="Maximize"
                                    Property="Visibility"
                                    Value="Visible" />
                            <Setter TargetName="Restore"
                                    Property="Visibility"
                                    Value="Collapsed" />
                        </Trigger>
                        <Trigger Property="ResizeMode"
                                 Value="NoResize">
                            <Setter TargetName="Minimize"
                                    Property="Visibility"
                                    Value="Collapsed" />
                            <Setter TargetName="Maximize"
                                    Property="Visibility"
                                    Value="Collapsed" />
                            <Setter TargetName="Restore"
                                    Property="Visibility"
                                    Value="Collapsed" />
                        </Trigger>

                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="ResizeMode"
                                           Value="CanResizeWithGrip" />
                                <Condition Property="WindowState"
                                           Value="Normal" />
                            </MultiTrigger.Conditions>
                            <Setter TargetName="ResizeGrip"
                                    Property="Visibility"
                                    Value="Visible" />
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>

    </Style>



    <Style TargetType="local:TransitioningContentControl">
        <Setter Property="IsTabStop"
                Value="False" />
        <Setter Property="HorizontalContentAlignment"
                Value="Stretch" />
        <Setter Property="VerticalContentAlignment"
                Value="Stretch" />
        <Setter Property="Transition"
                Value="DefaultTransition" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:TransitioningContentControl">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="2">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="PresentationStates">
                                <VisualState x:Name="DefaultTransition">
                                    <Storyboard>
                                        <!--<DoubleAnimationUsingKeyFrames 
                                            BeginTime="00:00:00" 
                                            Storyboard.TargetName="CurrentContentPresentationSite"
                                            Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="1"/>
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames
                                            BeginTime="00:00:00" 
                                            Storyboard.TargetName="PreviousContentPresentationSite" 
                                            Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="0"/>
                                        </DoubleAnimationUsingKeyFrames>-->
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="CurrentContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="0" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.400"
                                                                  Value="1" />
                                        </DoubleAnimationUsingKeyFrames>

                                        <DoubleAnimation BeginTime="00:00:00"
                                                         Duration="00:00:00.500"
                                                         Storyboard.TargetName="CurrentContentPresentationSite"
                                                         Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
                                                         From="50"
                                                         To="0">
                                            <DoubleAnimation.EasingFunction>
                                                <CubicEase EasingMode="EaseOut" />
                                            </DoubleAnimation.EasingFunction>
                                        </DoubleAnimation>

                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="PreviousContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="1" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.100"
                                                                  Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Normal">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="PreviousContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.Visibility)">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <Visibility>Collapsed</Visibility>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>

                                <VisualState x:Name="UpTransition">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="CurrentContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="0" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300"
                                                                  Value="1" />
                                        </DoubleAnimationUsingKeyFrames>

                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="CurrentContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="30" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300"
                                                                  Value="0" />
                                        </DoubleAnimationUsingKeyFrames>

                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="PreviousContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="1" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300"
                                                                  Value="0" />
                                        </DoubleAnimationUsingKeyFrames>

                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="PreviousContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="0" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300"
                                                                  Value="-30" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>

                                <VisualState x:Name="DownTransition">
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="CurrentContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="0" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300"
                                                                  Value="1" />
                                        </DoubleAnimationUsingKeyFrames>

                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="CurrentContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="-40" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300"
                                                                  Value="0" />
                                        </DoubleAnimationUsingKeyFrames>

                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="PreviousContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="1" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300"
                                                                  Value="0" />
                                        </DoubleAnimationUsingKeyFrames>

                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
                                                                       Storyboard.TargetName="PreviousContentPresentationSite"
                                                                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00"
                                                                  Value="0" />
                                            <SplineDoubleKeyFrame KeyTime="00:00:00.300"
                                                                  Value="40" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>

                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>

                        <Grid>
                            <ContentPresenter x:Name="PreviousContentPresentationSite"
                                              Content="{x:Null}"
                                              ContentTemplate="{TemplateBinding ContentTemplate}"
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                <ContentPresenter.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform />
                                        <SkewTransform />
                                        <RotateTransform />
                                        <TranslateTransform />
                                    </TransformGroup>
                                </ContentPresenter.RenderTransform>
                            </ContentPresenter>

                            <ContentPresenter x:Name="CurrentContentPresentationSite"
                                              Content="{x:Null}"
                                              ContentTemplate="{TemplateBinding ContentTemplate}"
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                <ContentPresenter.RenderTransform>
                                    <TransformGroup>
                                        <ScaleTransform />
                                        <SkewTransform />
                                        <RotateTransform />
                                        <TranslateTransform />
                                    </TransformGroup>
                                </ContentPresenter.RenderTransform>
                            </ContentPresenter>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>