65.9K
CodeProject 正在变化。 阅读更多。
Home

一致的窗口外观

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2009年6月17日

CPOL

2分钟阅读

viewsIcon

13400

一致的窗口外观

作为我在 CodeProject 上撰写的 WPF 初学者系列文章(WPF 初学者系列)的一部分,我刚开始撰写一篇关于 DependancyProperties 的文章。 作为其中的一部分,我开始编写一些演示项目,以向人们展示 DependancyProperties 的优点。 作为副作用,我不得不为这些演示想出一些不太复杂的实际用途。

我开始为附加的 DependancyProperties 编写一个,并意识到这实际上是一个相当好的想法。 想法是,你可能希望所有的应用程序窗口都具有相同的外观和感觉。 也许是顶部横幅、一些内容和底部的状态栏。 所以我对此进行了一些思考,并决定可以通过使用单个附加的 DependancyProperty 轻松实现这一点。

使用我的解决方案非常简单,如果你想使用“通用”的外观和感觉,只需在 XAML 或代码隐藏文件中窗口声明中设置一个 DP,就完成了。 让我们看看代码吧。

<Window x:Class=”Attached_Properties_DPs.Window1″
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
    xmlns:local=”clr-namespace:Attached_Properties_DPs”
    local:AttachedPropertyChildAdder.IsMasterHeaderApplied=”true”
    WindowStartupLocation=”CenterScreen”
    Title=”Attached_Properties_DPs” Height=”400″ Width=”600″>
        <!– Extra content will be added here at runtime if the
             local:AttachedPropertyChildAdder.
             IsMasterHeaderApplied=”true” is set to true
             try changing the value of this in the top of this
             file, set it false and run me.
             See that there is no header applied if its false,
             and there is if its true –>
        <Button x:Name=”btn1″ Content=”click me”
                Margin=”10,10,10,10″ Click=”btn1_Click”/>
</Window>

正如你所见,这个例子将 DP IsMasterHeaderApplied 设置为 true,这意味着这个窗口将使用通用的外观和感觉。 那么它是如何工作的呢? 好吧,这完全取决于 IsMasterHeaderApplied DP,如下所示

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Imaging; 

namespace Attached_Properties_DPs
{
    /// <summary>
    /// A simply show case, to demonstrate a usage of an attached
    /// DP property.
    /// This example lets Windows add a header portion to the their
    /// default content with some new Contents. Kind of like using
    /// Master Pages in ASP .NET
    /// </summary>
    public class AttachedPropertyChildAdder
    {
        #region Register IsMasterHeaderApplied DP
        public static readonly DependencyProperty
            IsMasterHeaderAppliedProperty =
            DependencyProperty.RegisterAttached(
                “IsMasterHeaderApplied”,
                typeof(Boolean),
                typeof(AttachedPropertyChildAdder),
                new FrameworkPropertyMetadata(
                    IsMasterHeaderAppliedChanged)); 

        public static void SetIsMasterHeaderApplied(
            DependencyObject element, Boolean value)
        {
            element.SetValue(IsMasterHeaderAppliedProperty, value);
        }
        public static Boolean GetIsMasterHeaderApplied(
            DependencyObject element)
        {
            return (Boolean)element.GetValue(
                IsMasterHeaderAppliedProperty);
        }
        #endregion 

        #region PropertyChanged callback 

        /// <summary>
        /// Is called whenever a user of the
        /// IsMasterHeaderApplied Attached DP changes
        /// the IsMasterHeaderApplied DP value
        /// </summary>
        /// <param name=”obj”></param>
        /// <param name=”args”></param>
        public static void IsMasterHeaderAppliedChanged(DependencyObject obj,
            DependencyPropertyChangedEventArgs args)
        {
            if ((bool)args.NewValue)
            {
                if (obj is Window)
                {
                    Window wnd = (Window)obj;
                    wnd.Loaded += new RoutedEventHandler(wnd_Loaded);
                }
            }
        } 

        /// <summary>
        /// Hook into the Window load event to replace the Content of the Window
        /// with some custom Content, to show case exactly how cool DPs are.
        ///
        /// In this example we are going to create a header for the Window.
        ///
        /// So setting the IsMasterHeaderApplied will make sure the Window
        /// gets a header applied.
        ///
        /// Kind of like Master Pages in ASP .NET
        /// </summary>
        public static void wnd_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                DockPanel dp = new DockPanel();
                dp.LastChildFill = true;
                StackPanel sp = new StackPanel();
                dp.Children.Add(sp);
                sp.Background = new SolidColorBrush(Colors.CornflowerBlue);
                sp.Orientation = Orientation.Vertical;
                sp.SetValue(DockPanel.DockProperty, Dock.Top);
                BitmapImage bitmap = new BitmapImage(
                    new Uri(“Images/Header.png”, UriKind.Relative));
                Image image = new Image();
                image.Source = bitmap;
                sp.Children.Add(image);
                UIElement el =
                    ((DependencyObject)sender as Window).Content as UIElement;
                el.SetValue(DockPanel.DockProperty, Dock.Bottom);
                ((DependencyObject)sender as Window).Content = null;
                dp.Children.Add(el);
               ((DependencyObject)sender as Window).Content = dp;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(
                    string.Format(“Exception : {0}”,ex.Message));
            }
        }
        #endregion
    }
}

正如所见,我们只是使用 Window.Loaded 事件,并保存原始窗口内容,然后创建“Common”布局,然后重新添加原始内容。

这保留了原始内容所拥有的所有 RoutedEvents 的连接。

这个例子只是在将 IsMasterHeaderApplied DP 设置为 true 的任何窗口的顶部显示一个图像横幅。 运行后,它看起来像这样

37362/logo-thumb.png

查看原始 XAML,你会看到它声明了 Button,但没有声明顶部横幅,这是由 IsMasterHeaderApplied DP 添加的。

好的,这是一个非常简单的例子,但是假设“Common”内容包含所有连接到 RoutedCommands 的菜单以及所有页脚/状态区域等。

我认为它会很好地工作。

© . All rights reserved.