zoukankan      html  css  js  c++  java
  • Creating a Base Window Class in WPF

    Unlike Windows Forms, there is no Visual Inheritance in WPF. Luckily you don’t need visual inheritance as you can use User Controls to get a re-usable UI. There are times, however, when you want a base Window class so you can have common functionality in all your WPF windows. To accomplish this you can create a base class from which all your WPF windows can inherit. To use the base class you will need to make one simple change in both the XAML and in your code-behind class.

    <Window> Element and Window Class

    When you add a new Window to a WPF application it builds a .XAML file and a code-behind file. The XAML file has a <Window> element and the code-behind file has a partial class that inherits from “Window” or “System.Windows.Window” to be more specific. Notice the x:Class=”<Namespace>.<ClassName>” syntax in the XAML (See Figure 1). This x:Class name attribute must have the same name as the partial class in the code-behind. At compile time, the .XAML file is converted into a partial class that has the same name as the name of the class in the code-behind and inherits from the name of the top level element in the XAML; in this case “Window”.


    Figure 1: The Window class and the inherited Window must match.

    As long as these two items match the two elements in the partial class in the code-behind the compiler will be happy. If either of these two elements does not match, you will receive a compiler error.

    Inherit from the Window Class

    Now that you understand the basics of how the XAML and the code-behind are put together, you can now create a base Window class and modify the XAML and code-behind to use this new class.

    If you wish to follow along with this article, create a new WPF application in Visual Studio. Add a new class to your project namedWindowBase. Modify this newly added class to inherit from the Window class. Add the following Imports/using statements at the top of the WindowBase class.

    C#
    using System.Windows;

    Visual Basic
    Imports System.Windows

    The WindowBase class needs to inherit from the Window class by changing the code to look like the following:

    C#
    using System;
    using System.Windows;

    namespace WpfApplication1
    {
      public class WindowBase : Window
      {
      }
    }


    Visual Basic
    Imports System.Windows

    Public Class WindowBase
      Inherits Window
    End Class

    Modify the code-behind of the Window1.xaml file to inherit from the WindowBase class you just created. Your Window1 code-behind should now look like the following:

    C#
    public partial class Window1 : WindowBase
    {
      public Window1()
      {
        InitializeComponent();
      }
    }

    Visual Basic
    Class Window1
      Inherits WindowBase

    End Class

    If you were to compile the WPF application right now, you will receive the error message “Base class 'System.Windows.Window' specified for class 'Window1' cannot be different from the base class 'WindowBase' of one of its other partial types.” The reason is because while you changed the code behind to inherit from the WindowBase class, you need to change the XAML markup to reflect this same change.

    The change you need to make is you need to modify the <Window> element to be <WindowBase>. However, <WindowBase> is not a part of any of the imported xml namespaces that are a normal part of the XAML markup. Thus, you need to add a namespace reference to the assembly that contains the WindowBase class. If you created a default WPF application project, the namespace you will add to the XAML is the following:

    xmlns:src="clr-namespace:WpfApplication1"

    Once you have added this namespace with the prefix of “src” you can now change the <Window> element to <src:WindowBase>. Be sure you modify the closing </Window> element to </src:WindowBase>. The complete source code for the XAML is shown below.

    C#
    <src:WindowBase
      x:Class="WpfApplication1.Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:src="clr-namespace:WpfApplication1"
      Title="Window1" Height="300" Width="300">
      <Grid></Grid>
    </src:WindowBase>

    Visual Basic
    <src:WindowBase
      x:Class="Window1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:src="clr-namespace:WpfApplication1"
      Title="Window1" Height="300" Width="300">
      <Grid></Grid>
    </src:WindowBase>

    At this point you should be able to compile the application and everything should compile correctly.

    Adding Functionality

    Now that you have a base Window class you can add code to that class that can be used in all of your WPF Windows. Once piece of functionality you might need is to check if your Window is in design mode or runtime. Add the following property to your WindowBase class.

    C#
    public bool IsInDesignMode
    {
      get
      {
        return System.ComponentModel.
                DesignerProperties.GetIsInDesignMode(this);
      }
    }

    Visual Basic
    Public ReadOnly Property IsInDesignMode() As Boolean
      Get
        Return System.ComponentModel. _
                DesignerProperties.GetIsInDesignMode(Me)
      End Get
    End Property

    From within your Window that inherits from the WindowBase class you can test to see if you are in design mode or in runtime mode.

    C#
    if(IsInDesignMode)
      // Do Something

    Visual Basic
    If IsInDesignMode Then
      ' Do Something
    End If

    Another piece of code that might come in handy in your WPF windows is the ability to read a resource dictionary XAML file and load it into the Resources of the Window. Below is the code you would add to the WindowBase class to do this.

    C#
    using System.IO;
    using System.Windows.Markup;

    public void OpenResourceDictionary(string fileName)
    {
      ResourceDictionary dic = null;

      if (File.Exists(fileName))
      {
        using (FileStream fs = new FileStream(fileName, FileMode.Open))
          dic = (ResourceDictionary)XamlReader.Load(fs);

        this.Resources.MergedDictionaries.Add(dic);
      }
      else
        throw new FileNotFoundException(
          "Can't open resource file: " + fileName +
          " in the method OpenResourceDictionary().");
    }

    Visual Basic
    Imports System.IO
    Imports System.Windows.Markup

    Public Sub OpenResourceDictionary(ByVal fileName As String)
      Dim dic As ResourceDictionary = Nothing

      If File.Exists(fileName) Then
        Using fs As New FileStream(fileName, FileMode.Open)
          dic = DirectCast(XamlReader.Load(fs), ResourceDictionary)
        End Using

        Me.Resources.MergedDictionaries.Add(dic)
      Else
        Throw New FileNotFoundException( _
          "Can't open resource file: " & fileName & _
          " in the method OpenResourceDictionary().")
      End If
    End Sub

    When you wish to load a new resource dictionary file at runtime into your Window you may do so with some very simple code from within your Window.

    C#
    OpenResourceDictionary("D:\Samples\Green.xaml");

    Visual Basic
    OpenResourceDictionary("D:\Samples\Green.xaml")

    Summary

    So, that is all there is to creating your own base Window class from which all your Window objects can inherit. There is a lot of functionality that you will want to make available to your Window classes. Creating a base Window class is a great way to expose this functionality. It just takes a little bit of tweaking to your XAML and your code-behind to get all this great functionality.


    NOTE: You can download the complete sample code at my website. http://www.pdsa.com/downloads. Choose Tips & Tricks, then "WPF Window Inheritance" from the drop-down.

    Good Luck With Your Coding,
    Paul Sheriff

    ** SPECIAL OFFER FOR MY BLOG READERS **
    Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".
    作者:Angelo Lee
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    dom2级事件兼容性写法
    cookie js案例
    cookie讲解
    js高级总结
    鼠标拖拽时,选择文字问题
    正则的细节
    正则捕获的细节及replace分析
    正则的使用及replace细讲
    while循环的讲解
    acwing 189. 乳草的入侵 bfs
  • 原文地址:https://www.cnblogs.com/yefengmeander/p/2887676.html
Copyright © 2011-2022 走看看