使用UI Automation實現自動化測試--1-4


Introduction

UI Automation是Microsoft .NET 3.0框架下提供的一種用於自動化測試的技術,是在MSAA基礎上建立的,MSAA就是Microsoft Active Accessibility。UI Automation在某些方面超過了MSAA,UI自動化提供了Windows Vista中,微軟Windows XP的全部功能,和Windows Server 2003。

在UI Automation中,所有的窗體、控件都表現為一個AutomationElement, AutomationElement 中包含此控件或窗體的屬性,在實現自動化的過程中,我們通過其相關屬性進行對控件自動化操作。對於UI用戶界面來說,所有顯示在桌面上的UI,其實際是一個UI Tree,根節點是desktop。我們可以使用UI Spy或者是SPY++來獲得Window和Control的相關信息。在UI Automation里,根節點表示為AutomationElemnet.RootElement. 通過根節點,我們可以通過窗體或控件的Process Id、Process Name或者Window Name找到相應的子AutomationElement,例如Dialog、Button、TextBox、Checkbox等標准控件,通過控件所對應的Pattern進行相關的操作。

UI Automation structure

 

如下圖所示:



1. 在服務端由UIAutomationProvider.dll和UIAutomationTypes.dll提供。

     2. 在客戶端由UIAutomationClient.dll和UIAutomationTypes.dll提供。

     3. UIAutomationCore.dll為UI自動化的核心部分,負責Server端和Client端的交互。

     4. UIAUtomationClientSideProvides.dll為客戶端程序提供自動化支持。

使用UI Automation實現自動化測試--2

本文通過一個實例來介紹怎樣使用UI Automation實現軟件的自動化測試。

1. 首先建立一個待測試的winform程序,即UI Automation的服務端。

 

 

下面是button事件處理程序。

 

private void button1_Click(object sender, EventArgs e)

{

     int i = int.Parse(textBox1.Text);

     int j = int.Parse(textBox2.Text);

     textBox3.Text = (i + j).ToString();

}

2. 建立一個測試程序,做UI Automaion的客戶端。

添加引用:UIAutomationClient.dll 和 UIAutomationTypes.dll

 

using System;
  2 using System.Diagnostics;
  3 using System.Threading;
  4 using System.Windows.Automation.Provider;
  5 using System.Windows.Automation.Text;
  6 using System.Windows.Automation;
  7
  8 namespace UIAutomationTest
  9 {
 10    class Program
 11    {
 12        static void Main(string[] args)
 13        {
 14            try
 15            {
 16                Console.WriteLine("\nBegin WinForm UIAutomation test run\n");
 17                // launch Form1 application
 18                // get refernce to main Form control
 19                // get references to user controls
 20                // manipulate application
 21                // check resulting state and determine pass/fail
 22
 23                Console.WriteLine("\nBegin WinForm UIAutomation test run\n");
 24                Console.WriteLine("Launching WinFormTest application");
 25                //啟動被測試的程序
 26                Process p = Process.Start(@"E:\Project\WinFormTest\WinFormTest\bin\Debug\WinFormTest.exe");
 27
 28                //自動化根元素
 29                AutomationElement aeDeskTop = AutomationElement.RootElement;
 30
 31                Thread.Sleep(2000);
 32                AutomationElement aeForm = AutomationElement.FromHandle(p.MainWindowHandle);
 33                //獲得對主窗體對象的引用,該對象實際上就是 Form1 應用程序(方法一)
 34                //if (null == aeForm)
 35                //{
 36                //    Console.WriteLine("Can not find the WinFormTest from.");
 37                //}
 38
 39                //獲得對主窗體對象的引用,該對象實際上就是 Form1 應用程序(方法二)
 40                int numWaits = 0;
 41                do
 42                {
 43                    Console.WriteLine("Looking for WinFormTest……");
 44                    //查找第一個自動化元素
 45                    aeForm = aeDeskTop.FindFirst(TreeScope.Children, new PropertyCondition(
 46                        AutomationElement.NameProperty, "Form1"));
 47                    ++numWaits;
 48                    Thread.Sleep(100);
 49                } while (null == aeForm && numWaits < 50);
 50                if (null == aeForm)
 51                    throw new NullReferenceException("Failed to find WinFormTest.");
 52                else
 53                    Console.WriteLine("Found it!");
 54
 55                Console.WriteLine("Finding all user controls");
 56                //找到第一次出現的Button控件
 57                AutomationElement aeButton = aeForm.FindFirst(TreeScope.Children,
 58                  new PropertyCondition(AutomationElement.NameProperty, "button1"));
 59
 60                //找到所有的TextBox控件
 61                AutomationElementCollection aeAllTextBoxes = aeForm.FindAll(TreeScope.Children,
 62                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
 63
 64                // 控件初始化的順序是先初始化后添加到控件
 65                // this.Controls.Add(this.textBox3);                  
 66                // this.Controls.Add(this.textBox2);
 67                // this.Controls.Add(this.textBox1);
 68
 69                AutomationElement aeTextBox1 = aeAllTextBoxes[2];
 70                AutomationElement aeTextBox2 = aeAllTextBoxes[1];
 71                AutomationElement aeTextBox3 = aeAllTextBoxes[0];
 72
 73                Console.WriteLine("Settiing input to '30'");
 74                //通過ValuePattern設置TextBox1的值
 75                ValuePattern vpTextBox1 = (ValuePattern)aeTextBox1.GetCurrentPattern(ValuePattern.Pattern);
 76                vpTextBox1.SetValue("30");
 77                Console.WriteLine("Settiing input to '50'");
 78                //通過ValuePattern設置TextBox2的值
 79                ValuePattern vpTextBox2 = (ValuePattern)aeTextBox2.GetCurrentPattern(ValuePattern.Pattern);
 80                vpTextBox2.SetValue("50");
 81                Thread.Sleep(1500);
 82                Console.WriteLine("Clickinig on button1 Button.");
 83                //通過InvokePattern模擬點擊按鈕
 84                InvokePattern ipClickButton1 = (InvokePattern)aeButton.GetCurrentPattern(InvokePattern.Pattern);
 85                ipClickButton1.Invoke();
 86                Thread.Sleep(1500);
 87
 88                //驗證計算的結果與預期的結果是否相符合
 89                Console.WriteLine("Checking textBox3 for '80'");
 90                TextPattern tpTextBox3 = (TextPattern)aeTextBox3.GetCurrentPattern(TextPattern.Pattern);
 91                string result = tpTextBox3.DocumentRange.GetText(-1);//獲取textbox3中的值
 92                //獲取textbox3中的值
 93                //string result = (string)aeTextBox2.GetCurrentPropertyValue(ValuePattern.ValueProperty);
 94                if ("80" == result)
 95                {
 96                    Console.WriteLine("Found it.");
 97                    Console.WriteLine("TTest scenario: *PASS*");
 98                }
 99                else
100                {
101                    Console.WriteLine("Did not find it.");
102                    Console.WriteLine("Test scenario: *FAIL*");
103                }
104
105                Console.WriteLine("Close application in 5 seconds.");
106                Thread.Sleep(5000);
107                //實現關閉被測試程序
108                WindowPattern wpCloseForm = (WindowPattern)aeForm.GetCurrentPattern(WindowPattern.Pattern);
109                wpCloseForm.Close();
110
111                Console.WriteLine("\nEnd test run\n");
112            }
113            catch (Exception ex)
114            {
115                Console.WriteLine("Fatal error: " + ex.Message);
116            }
117        }
118    }
119}
120


 

使用UI Automation實現自動化測試--3

Chapter 3  UI Automation中的幾個重要屬性

Control Tree of the AutomationElement

在UI Automation控件樹中,根節點為Desktop window, 其他運行在用戶桌面的窗體都作為Desktop window的子節點。

如下圖所示:
            

Desktop window可通過AutomationElement.RootElement屬性獲取,子節點中的窗體或對話框可通過

AutomationElement.RootElement.FindAll(TreeScope.Descendants, condition)


AutomationElement.RootElement.FindFirt(TreeScope.Descendants, condition)來獲取.

 

 

AutomationElement property

 

在UI Automation中有如下幾個重要屬性:

  1. AutomationIdProperty: 通過AutomationId來查找AutomationElement。
  2. NameProperty:通過控件的Name屬性來查找AutomationElement。
  3. ControlType:通過控件的類型來查找AutomationElement
  4. AutomationId: 唯一地標識自動化元素,將其與同級相區分。
  5. Name:  WPF 按鈕的Content 屬性、Win32 按鈕的Caption 屬性以及 HTML 圖像的ALT 屬性都映射到 UI 自動化視圖中的同一個屬性 Name

 

注:PropertyCondition類是用來對相關屬性進行條件匹配,在控件樹中查找控件時,可以通過最佳匹配來找到相應的控件。

如下代碼列出了使用不同的屬性來構建PropertyCondition,通過PropertyCondition來查找控件樹中的控件.
 

 

 

 


public class PropertyConditions
    {
        static PropertyCondition propertyCondition;

        /// <summary>
        /// Create PropertyCondition by AutomationId
        /// </summary>
        /// <param name="automationId">Control AutomationId</param>
        /// <returns>Return PropertyCondition instance</returns>
        public static PropertyCondition GetAutomationIdProperty(object automationId)
        {
            propertyCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, automationId);
            return propertyCondition;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="controlType"></param>
        /// <returns></returns>
        public static PropertyCondition GetControlTypeProperty(object controlType)
        {
            propertyCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, controlType);
            return propertyCondition;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="controlName"></param>
        /// <returns></returns>
        public static PropertyCondition GetNameProperty(object controlName)
        {
            propertyCondition = new PropertyCondition(AutomationElement.NameProperty, controlName);
            return propertyCondition;
        }

        /// <summary>
        /// Find element by specific PropertyCondition
        /// </summary>
        /// <param name="condition">PropertyCondition instance</param>
        /// <returns>Target automation element</returns>
        public static AutomationElement FindElement(PropertyCondition condition)
        {
            return AutomationElement.RootElement.FindFirst(TreeScope.Descendants, condition);
        }
    }

使用UI Automation實現自動化測試--4.1 (DockPattern)

DockPattern用於操作可停靠容器控件,我們最熟悉的VS2005/2008中的ToolBox,Solution Explorer都可以設置不同的DockPosition, 但是目前並不支持DockPattern,所以無法做為實例來講。使用DockPattern的前提為控件支持DockPattern。 DockPattern中的DockPosition有六個枚舉變量,即Bottom、Left、Right、Top、Fill和None。如果控件支持DockPattern, 則可以獲取相對應的DockPosition以及設置控件的DockPosition。

如下代碼是獲取控件的DockPattern、獲取控件當前的DockPosition以及設置控件的DockPosition。

 

 


#region DockPattern helper

        /// <summary>
        /// Get DockPattern
        /// </summary>
        /// <param name="element">AutomationElement instance</param>
        /// <returns>DockPattern instance</returns>
        public static DockPattern GetDockPattern(AutomationElement element)
        {
            object currentPattern;
            if (!element.TryGetCurrentPattern(DockPattern.Pattern, out currentPattern))
            {
                throw new Exception(string.Format("Element with AutomationId '{0}' and Name '{1}' does not support the DockPattern.",
                    element.Current.AutomationId, element.Current.Name));
            }
            return currentPattern as DockPattern;
        }

        /// <summary>
        /// Get DockPosition
        /// </summary>
        /// <param name="element">AutomationElement instance</param>
        /// <returns>DockPosition instance</returns>
        public static DockPosition GetDockPosition(AutomationElement element)
        {
            return GetDockPattern(element).Current.DockPosition;
        }

        /// <summary>
        /// Set DockPosition
        /// </summary>
        /// <param name="element">AutomationElement instance</param>
        public static void SetDockPattern(AutomationElement element, DockPosition dockPosition)
        {
            GetDockPattern(element).SetDockPosition(dockPosition);
        }

        #endregion

使用UI Automation實現自動化測試--4.2 (ExpandCollapsePattern)

ExpandCollapsePattern

表示以可視方式進行展開(以顯示內容)和折疊(以隱藏內容)的控件。例如ComboBox控件支持ExpandCollapsePattern。

ExpandCollapsePattern有兩個主要方法:

Expand()方法:隱藏 AutomationElement 的全部子代節點、控件或內容。

Collapse()方法:顯示 AutomationElement 的全部子節點、控件或內容。

      以下代碼是用ExpandCollapsePattern來測試ComboBox控件的Expand和Collapse。


using System;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;

namespace UIATest
{
    class Program
    {
        static void Main(string[] args)
        {
            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
            int processId = process.Id;
            AutomationElement element = FindElementById(processId, "comboBox1");
            ExpandCollapsePattern currentPattern = GetExpandCollapsePattern(element);
            currentPattern.Expand();
            Thread.Sleep(1000);
            currentPattern.Collapse();
        }

        /// <summary>
        /// Get the automation elemention of current form.
        /// </summary>
        /// <param name="processId">Process Id</param>
        /// <returns>Target element</returns>
        public static AutomationElement FindWindowByProcessId(int processId)
        {
            AutomationElement targetWindow = null;
            int count = 0;
            try
            {
                Process p = Process.GetProcessById(processId);
                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
                return targetWindow;
            }
            catch (Exception ex)
            {
                count++;
                StringBuilder sb = new StringBuilder();
                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
                if (count > 5)
                {
                    throw new InvalidProgramException(message, ex);
                }
                else
                {
                    return FindWindowByProcessId(processId);
                }
            }
        }


        /// <summary>
        /// Get the automation element by automation Id.
        /// </summary>
        /// <param name="windowName">Window name</param>
        /// <param name="automationId">Control automation Id</param>
        /// <returns>Automatin element searched by automation Id</returns>
        public static AutomationElement FindElementById(int processId, string automationId)
        {
            AutomationElement aeForm = FindWindowByProcessId(processId);
            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
            return tarFindElement;
        }

        ExpandCollapsePattern helper
    }
}

      以下代碼為被測程序的xaml文件:


 1<Window x:Class="WpfApp.Window1"
 2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4    Title="Window1" Height="219" Width="353">
 5    <Grid>
 6        <ComboBox Name="comboBox1" Height="23" VerticalAlignment="Top" Margin="94,58,0,0" HorizontalAlignment="Left" Width="119">
 7            <ComboBoxItem>kaden</ComboBoxItem>
 8            <ComboBoxItem>sam</ComboBoxItem>
 9        </ComboBox>
10    </Grid>
11</Window>

InvokePattern

InvokePatternUIA中最常用的Pattern之一,WPFWinform中的button控件都支持InvokePattern

InvokePatternInvoke()方法的調用應立即返回,沒有出現阻止情況。但是,此行為完全依賴於 Microsoft UI 自動化提供程序實現。在調用 Invoke() 會引起阻止問題(如Winform中的模式對話框,但是WPF中的對話框的處理方式和winform不同,所以可以使用Invoke()方法來操作WPF中的模式對話框,因為WPF中的模式對話框不會出現阻止的問題)的情況下,要調用此方法,則需要另起線程來操作。

 


using System;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;

namespace UIATest
{
    class Program
    {
        static void Main(string[] args)
        {
            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
            int processId = process.Id;
            AutomationElement element = FindElementById(processId, "button1");
            InvokePattern currentPattern = GetInvokePattern(element);
            currentPattern.Invoke();
        }

        /// <summary>
        /// Get the automation elemention of current form.
        /// </summary>
        /// <param name="processId">Process Id</param>
        /// <returns>Target element</returns>
        public static AutomationElement FindWindowByProcessId(int processId)
        {
            AutomationElement targetWindow = null;
            int count = 0;
            try
            {
                Process p = Process.GetProcessById(processId);
                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
                return targetWindow;
            }
            catch (Exception ex)
            {
                count++;
                StringBuilder sb = new StringBuilder();
                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
                if (count > 5)
                {
                    throw new InvalidProgramException(message, ex);
                }
                else
                {
                    return FindWindowByProcessId(processId);
                }
            }
        }


        /// <summary>
        /// Get the automation element by automation Id.
        /// </summary>
        /// <param name="windowName">Window name</param>
        /// <param name="automationId">Control automation Id</param>
        /// <returns>Automatin element searched by automation Id</returns>
        public static AutomationElement FindElementById(int processId, string automationId)
        {
            AutomationElement aeForm = FindWindowByProcessId(processId);
            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
            return tarFindElement;
        }

        #region InvokePattern helper
        /// <summary>
        /// Get InvokePattern
        /// </summary>
        /// <param name="element">AutomationElement instance</param>
        /// <returns>InvokePattern instance</returns>
        public static InvokePattern GetInvokePattern(AutomationElement element)
        {
            object currentPattern;
            if (!element.TryGetCurrentPattern(InvokePattern.Pattern, out currentPattern))
            {
                throw new Exception(string.Format("Element with AutomationId '{0}' and Name '{1}' does not support the InvokePattern.",
                    element.Current.AutomationId, element.Current.Name));
            }
            return currentPattern as InvokePattern;
        }

        #endregion
    }
}


被測程序xaml代碼如下:


<Window x:Class="WpfApp.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="219" Width="353">
    <Grid>
        <Button Height="23" HorizontalAlignment="Left" Click="button1_Click" Margin="50,0,0,62" Name="button1" VerticalAlignment="Bottom" Width="75">Button</Button>
    </Grid>
</Window>


對應的cs文件:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Use InvokePattern invoke button.");
        }
    }
}

      本文主要針對InvokePattern的Invoke方法來操作button控件。

使用UI Automation實現自動化測試--4.4 (ValuePattern)

ValuePatternUI Automation中最常見的Pattern之一,WinformWPFTextBox控件都支持ValuePattern

ValuePattern的一個重要的方法是SetValue,在允許調用 SetValue 之前,控件應將其 IsEnabledProperty 設置為 true 並將其 IsReadOnlyProperty 設置為 false

通過ValuePatternCurrent屬性可以獲得控件的valueIsReadOnly屬性。

實現 Value 控件模式時,請注意以下准則和約定:

如果任何項的值是可編輯的,則諸如 ListItem  TreeItem 等控件必須支持 ValuePattern,而不管控件的當前編輯模式如何。如果子項是可編輯的,則父控件還必須支持ValuePattern

    下面的例子是通過ValuePattern來給TextBox設置和獲取值:


 1using System;
 2using System.Text;
 3using System.Diagnostics;
 4using System.Threading;
 5using System.Windows.Automation;
 6
 7namespace UIATest
 8{
 9    class Program
10    {
11        static void Main(string[] args)
12        {
13            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14            int processId = process.Id;
15            AutomationElement element = FindElementById(processId, "textBox1");
16            ValuePattern currentPattern = GetValuePattern(element);
17            Console.WriteLine("Is read only:'{0}', TextBox text is:'{1}'", currentPattern.Current.IsReadOnly, currentPattern.Current.Value);
18            currentPattern.SetValue("KadenKang");
19            Console.WriteLine("After using the SetValue, the TextBox value is '{0}'", currentPattern.Current.Value);
20            
21        }
22
23        /// <summary>
24        /// Get the automation elemention of current form.
25        /// </summary>
26        /// <param name="processId">Process Id</param>
27        /// <returns>Target element</returns>
28        public static AutomationElement FindWindowByProcessId(int processId)
29        {
30            AutomationElement targetWindow = null;
31            int count = 0;
32            try
33            {
34                Process p = Process.GetProcessById(processId);
35                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
36                return targetWindow;
37            }
38            catch (Exception ex)
39            {
40                count++;
41                StringBuilder sb = new StringBuilder();
42                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
43                if (count > 5)
44                {
45                    throw new InvalidProgramException(message, ex);
46                }
47                else
48                {
49                    return FindWindowByProcessId(processId);
50                }
51            }
52        }
53
54        /// <summary>
55        /// Get the automation element by automation Id.
56        /// </summary>
57        /// <param name="windowName">Window name</param>
58        /// <param name="automationId">Control automation Id</param>
59        /// <returns>Automatin element searched by automation Id</returns>
60        public static AutomationElement FindElementById(int processId, string automationId)
61        {
62            AutomationElement aeForm = FindWindowByProcessId(processId);
63            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
64            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
65            return tarFindElement;
66        }
67
68        ValuePattern helper
87    }
88}
89

 

下面的代碼是xaml設計:

 


1<Window x:Class="WpfApp.Window1"
2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4    Title="Window1" Height="219" Width="353">
5    <Grid>
6        <TextBox Height="23" Margin="50,20,160,0" Name="textBox1" VerticalAlignment="Top" MaxLength="5">textBox text</TextBox>
7    </Grid>
8</Window>
9

     本文通過簡單的實例介紹了UI Automation中的ValuePattern及其使用方法。

使用UI Automation實現自動化測試--4.5 (WindowPattern)

WindowPattern 控件模式用於支持在傳統的 圖形用戶界面 (GUI) 內提供基於基本窗口的功能的控件。必須實現此控件模式的控件的示例包括頂級應用程序窗口、多文檔界面 (MDI) 子窗口、大小可調的拆分窗格控件、模式對話框以及氣球狀幫助窗口。可以使用WindowPattern來對window進行操作,例如驗證window是否激活,是否最大化、最小化、正常模式以及關閉window等。
     下面的代碼演示了WindowPattern的使用方法: 


 1using System;
 2using System.Text;
 3using System.Diagnostics;
 4using System.Threading;
 5using System.Windows.Automation;
 6
 7namespace UIATest
 8{
 9    class Program
10    {
11        static void Main(string[] args)
12        {
13            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14            int processId = process.Id;
15            AutomationElement element = FindWindowByProcessId(processId);
16            WindowPattern currentPattern = GetWindowPattern(element);
17            
18            //Set window visual state to Maximized
19            currentPattern.SetWindowVisualState(WindowVisualState.Maximized);
20            Thread.Sleep(1000);
21
22            //Set window visual state to Normal
23            currentPattern.SetWindowVisualState(WindowVisualState.Normal);
24            Thread.Sleep(1000);
25
26            //Set window visual state to Minimized
27            currentPattern.SetWindowVisualState(WindowVisualState.Minimized);
28            
29            //Close window
30            currentPattern.Close();            
31        }
32
33        /// <summary>
34        /// Get the automation elemention of current form.
35        /// </summary>
36        /// <param name="processId">Process Id</param>
37        /// <returns>Target element</returns>
38        public static AutomationElement FindWindowByProcessId(int processId)
39        {
40            AutomationElement targetWindow = null;
41            int count = 0;
42            try
43            {
44                Process p = Process.GetProcessById(processId);
45                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
46                return targetWindow;
47            }
48            catch (Exception ex)
49            {
50                count++;
51                StringBuilder sb = new StringBuilder();
52                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
53                if (count > 5)
54                {
55                    throw new InvalidProgramException(message, ex);
56                }
57                else
58                {
59                    return FindWindowByProcessId(processId);
60                }
61            }
62        }
63
64        WindowPattern helper
83    }
84}

使用UI Automation實現自動化測試--4.6.1 (SelectionItemPattern)

SelectionItemPattern

支持SelectionItemPattern的控件有ListViewListBoxRadioButtonGridView等。

  1. 1.         SelectionItemPattern的三個重要方法:
  2. 1.         AddToSelection:將當前元素添加到所選項的集合。
  3. 2.         RemoveFromSelection: 從選定項的集合中移除當前元素。
  4. 3.         Select: 取消所有已選中的項,然后選擇當前元素。
  5. 2.         SelectionItemPatternCurrent屬性
    可通過Current屬性的IsSelected屬性來判斷AutomationElement是否被selected.

     如下代碼演示了使用SelectionItemPattern來操作RadioButton控件。


 1using System;
 2using System.Text;
 3using System.Diagnostics;
 4using System.Threading;
 5using System.Windows.Automation;
 6
 7namespace UIATest
 8{
 9    class Program
10    {
11        static void Main(string[] args)
12        {
13            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14            int processId = process.Id;
15
16            AutomationElement element = FindElementById(processId, "radioButton1");
17            SelectionItemPattern selectionItemPattern = GetSelectionItemPattern(element);
18            selectionItemPattern.Select();
19        }
20
21        /// <summary>
22        /// Get the automation elemention of current form.
23        /// </summary>
24        /// <param name="processId">Process Id</param>
25        /// <returns>Target element</returns>
26        public static AutomationElement FindWindowByProcessId(int processId)
27        {
28            AutomationElement targetWindow = null;
29            int count = 0;
30            try
31            {
32                Process p = Process.GetProcessById(processId);
33                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
34                return targetWindow;
35            }
36            catch (Exception ex)
37            {
38                count++;
39                StringBuilder sb = new StringBuilder();
40                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
41                if (count > 5)
42                {
43                    throw new InvalidProgramException(message, ex);
44                }
45                else
46                {
47                    return FindWindowByProcessId(processId);
48                }
49            }
50        }
51
52
53        /// <summary>
54        /// Get the automation element by automation Id.
55        /// </summary>
56        /// <param name="windowName">Window name</param>
57        /// <param name="automationId">Control automation Id</param>
58        /// <returns>Automatin element searched by automation Id</returns>
59        public static AutomationElement FindElementById(int processId, string automationId)
60        {
61            AutomationElement aeForm = FindWindowByProcessId(processId);
62            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
63            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
64            return tarFindElement;
65        }
66
67        SelectItemPattern
86    }
87}
88

     以下代碼為XAML:


1<Window x:Class="WpfApp.Window1"
2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4    Title="Window1" Height="219" Width="353">
5    <Grid>
6        <RadioButton Height="16" HorizontalAlignment="Right" Margin="0,46,10,0" Name="radioButton1" VerticalAlignment="Top" Width="120">RadioButton</RadioButton>
7    </Grid>
8</Window>
9

 

    本文簡單介紹了SelectionItemPattern以及使用SelectionItemPattern來操作RadioButton。

使用UI Automation實現自動化測試--4.6.2 (SelectItemPattern Demo)

 如下代碼演示了使用SelectionItemPattern來實現listview item 的多選操作:


  1using System;
  2using System.Text;
  3using System.Diagnostics;
  4using System.Threading;
  5using System.Windows.Automation;
  6
  7namespace UIATest
  8{
  9    class Program
 10    {
 11        static void Main(string[] args)
 12        {
 13            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
 14            int processId = process.Id;
 15
 16            Thread.Sleep(1000);
 17            MutlSelect(new int[] { 0, 1 }, processId, false);
 18        }
 19
 20        /// <summary>
 21        /// Get the automation elemention of current form.
 22        /// </summary>
 23        /// <param name="processId">Process Id</param>
 24        /// <returns>Target element</returns>
 25        public static AutomationElement FindWindowByProcessId(int processId)
 26        {
 27            AutomationElement targetWindow = null;
 28            int count = 0;
 29            try
 30            {
 31                Process p = Process.GetProcessById(processId);
 32                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
 33                return targetWindow;
 34            }
 35            catch (Exception ex)
 36            {
 37                count++;
 38                StringBuilder sb = new StringBuilder();
 39                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
 40                if (count > 5)
 41                {
 42                    throw new InvalidProgramException(message, ex);
 43                }
 44                else
 45                {
 46                    return FindWindowByProcessId(processId);
 47                }
 48            }
 49        }
 50
 51
 52        /// <summary>
 53        /// Get the automation element by automation Id.
 54        /// </summary>
 55        /// <param name="windowName">Window name</param>
 56        /// <param name="automationId">Control automation Id</param>
 57        /// <returns>Automatin element searched by automation Id</returns>
 58        public static AutomationElement FindElementById(int processId, string automationId)
 59        {
 60            AutomationElement aeForm = FindWindowByProcessId(processId);
 61            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
 62            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
 63            return tarFindElement;
 64        }
 65        
 66        /// <summary>
 67        /// Bulk select the list item
 68        /// </summary>
 69        /// <param name="indexes">List item index collection</param>
 70        /// <param name="processId">Application process Id</param>
 71        /// <param name="isSelectAll">Is select all or not</param>
 72        public static void MutlSelect(int[] indexes, int processId, bool isSelectAll)
 73        {
 74            AutomationElement targetElement = FindElementById(processId, "listView1");
 75
 76            AutomationElementCollection rows =
 77                targetElement.FindAll(TreeScope.Descendants,
 78                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
 79
 80            object multiSelect;
 81
 82            if (isSelectAll)
 83            {
 84                for (int i = 1; i < rows.Count - 1; i++)
 85                {
 86                    if (rows[i].TryGetCurrentPattern(SelectionItemPattern.Pattern, out multiSelect))
 87                    {
 88                        (multiSelect as SelectionItemPattern).AddToSelection();
 89                    }
 90                }
 91            }
 92            else
 93            {
 94                if (indexes.Length > 0)
 95                {
 96                    for (int j = 0; j < indexes.Length; j++)
 97                    {
 98                        int tempIndex = indexes[j];
 99                        if (rows[tempIndex].TryGetCurrentPattern(SelectionItemPattern.Pattern, out multiSelect))
100                        {
101                            (multiSelect as SelectionItemPattern).AddToSelection();
102                        }
103                    }
104                }
105            }
106        }
107
108        SelectItemPattern
127    }
128}

      如下代碼為對應的XAML:


 1<Window x:Class="WpfApp.Window2"
 2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4    Title="Window2" Height="412" Width="585">
 5    <Grid>
 6        <ListView Margin="2,97,0,163" Name="listView1">
 7            <ListViewItem>Kaden</ListViewItem>
 8            <ListViewItem>KangYi</ListViewItem>
 9            <ListViewItem>John</ListViewItem>
10        </ListView>
11    </Grid>
12</Window>
13

使用UI Automation實現自動化測試--4.7 (TogglePattern)

TogglePattern

支持TogglePattern的控件有CheckBoxTreeView中的button控件等。

  1. 1.       TogglePattern的方法

Toggle方法用於操作可以循環通過的一組狀態並在設置后保持某種狀態。

  1. 2.       TogglePattern屬性

Current屬性中的ToggleState有如下三種狀態:

  1. 1.         On
  2. 2.         Off
  3. 3.         Indeterminate

    如下代碼演示了使用TogglePattern來操作CheckBox控件。

 


 1using System;
 2using System.Text;
 3using System.Diagnostics;
 4using System.Threading;
 5using System.Windows.Automation;
 6
 7namespace UIATest
 8{
 9    class Program
10    {
11        static void Main(string[] args)
12        {
13            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14            int processId = process.Id;
15
16            Thread.Sleep(1000);
17            AutomationElement element = FindElementById(processId, "checkBox1");
18            TogglePattern togglePattern = GetTogglePattern(element);
19            togglePattern.Toggle();
20        }
21
22        /// <summary>
23        /// Get the automation elemention of current form.
24        /// </summary>
25        /// <param name="processId">Process Id</param>
26        /// <returns>Target element</returns>
27        public static AutomationElement FindWindowByProcessId(int processId)
28        {
29            AutomationElement targetWindow = null;
30            int count = 0;
31            try
32            {
33                Process p = Process.GetProcessById(processId);
34                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
35                return targetWindow;
36            }
37            catch (Exception ex)
38            {
39                count++;
40                StringBuilder sb = new StringBuilder();
41                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
42                if (count > 5)
43                {
44                    throw new InvalidProgramException(message, ex);
45                }
46                else
47                {
48                    return FindWindowByProcessId(processId);
49                }
50            }
51        }
52
53        /// <summary>
54        /// Get the automation element by automation Id.
55        /// </summary>
56        /// <param name="windowName">Window name</param>
57        /// <param name="automationId">Control automation Id</param>
58        /// <returns>Automatin element searched by automation Id</returns>
59        public static AutomationElement FindElementById(int processId, string automationId)
60        {
61            AutomationElement aeForm = FindWindowByProcessId(processId);
62            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
63            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
64            return tarFindElement;
65        }
66
67        TogglePattern helper
83    }
84}
85

     如下代碼為對應的XAML:


1<Window x:Class="WpfApp.Window1"
2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4    Title="Window1" Height="219" Width="353">
5    <Grid>
6        <CheckBox HorizontalAlignment="Right" Margin="0,75,10,89" Name="checkBox1" Width="120">CheckBox</CheckBox>
7    </Grid>
8</Window>

 

使用UI Automation實現自動化測試--4.8 (GridPattern)

GridPattern

支持GridPattern的最常見的控件為GridView WPF中使用ListViewGridView組合即可得到相應的GridView

GridPattern的方法

GetItem:此方法有兩個參數,即DataGridRowColumn

通過GridPatternGetItem方法可以獲取DataGrid中的某個確定的單元格,進而對單元進行操作。

對單元格的操作主要有以下幾個方面:

  1. 1.       編輯單元個中的數據。
  2. 2.       獲取單元格中的數據。
  3. 3.       獲取單元格中嵌套的AutomationElement(一般使用與自定義控件中)。

GridPattern的屬性

GridPatternCurrent屬性中有如下兩個屬性:

  1. 1.       RowCount屬性:GridPattern二維表格的行數。
  2. 2.       ColumnCount屬性:GridPattern二維表格列數。

下面我們通過一個實例來演示自動化測試中如何使用GridPattern來測試GridView的方法:


 1using System;
 2using System.Text;
 3using System.Diagnostics;
 4using System.Threading;
 5using System.Windows.Automation;
 6
 7namespace UIATest
 8{
 9    class Program
10    {
11        static void Main(string[] args)
12        {
13            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
14            int processId = process.Id;
15            Thread.Sleep(1000);
16
17            GridPattern Test
30        }
31
32        /// <summary>
33        /// Get the automation elemention of current form.
34        /// </summary>
35        /// <param name="processId">Process Id</param>
36        /// <returns>Target element</returns>
37        public static AutomationElement FindWindowByProcessId(int processId)
38        {
39            AutomationElement targetWindow = null;
40            int count = 0;
41            try
42            {
43                Process p = Process.GetProcessById(processId);
44                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
45                return targetWindow;
46            }
47            catch (Exception ex)
48            {
49                count++;
50                StringBuilder sb = new StringBuilder();
51                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
52                if (count > 5)
53                {
54                    throw new InvalidProgramException(message, ex);
55                }
56                else
57                {
58                    return FindWindowByProcessId(processId);
59                }
60            }
61        }
62
63        /// <summary>
64        /// Get the automation element by automation Id.
65        /// </summary>
66        /// <param name="windowName">Window name</param>
67        /// <param name="automationId">Control automation Id</param>
68        /// <returns>Automatin element searched by automation Id</returns>
69        public static AutomationElement FindElementById(int processId, string automationId)
70        {
71            AutomationElement aeForm = FindWindowByProcessId(processId);
72            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
73            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
74            return tarFindElement;
75        }
76
77        GridPattern helper
95    }
96}
97

 

    對應的XAML代碼如下:

 


 1<Window x:Class="WpfApp.GridView"
 2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4    Title="GridView" Height="426" Width="558">
 5    <Grid>
 6        <!--將鼠標放在方框的邊緣點擊就會產生相應的分割線生成Grid.RowDefinitions-->
 7        <Grid.RowDefinitions>
 8            <!--Auto,實際作用就是取實際控件所需的最小值;值為*或N*,實際作用就是取盡可能大的值;數字,絕對尺寸-->
 9            <RowDefinition Height="*" />
10            <RowDefinition Height="auto" MinHeight="95" />
11            <RowDefinition Height="22" />
12        </Grid.RowDefinitions>
13        <ListView Name="listview1" MinWidth="280" Grid.RowSpan="2" MouseMove="listview1_MouseMove">
14            <ListView.View>
15                <GridView x:Name="gridView1">
16                    <GridViewColumn Header="EmployeeID" DisplayMemberBinding="{Binding Path=EmployeeID}"></GridViewColumn>
17                    <GridViewColumn Header="FirstName" DisplayMemberBinding="{Binding Path=FirstName}"></GridViewColumn>
18                    <GridViewColumn Header="LastName" DisplayMemberBinding="{Binding Path=LastName}"></GridViewColumn>
19                    <GridViewColumn Header="Address" DisplayMemberBinding="{Binding Path=Address}"></GridViewColumn>
20                </GridView>
21            </ListView.View>
22        </ListView>
23    </Grid>
24
25</Window>
26

 

    GridView窗體后台代碼如下:

 


 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5using System.Windows;
 6using System.Windows.Controls;
 7using System.Windows.Data;
 8using System.Windows.Documents;
 9using System.Windows.Input;
10using System.Windows.Media;
11using System.Windows.Media.Imaging;
12using System.Windows.Shapes;
13using System.Data.SqlClient;
14using System.Data;
15
16namespace WpfApp
17{
18    /// <summary>
19    /// Interaction logic for GridView.xaml
20    /// </summary>
21    public partial class GridView : Window
22    {
23        public GridView()
24        {
25            InitializeComponent();
26            getData();
27        }
28        SqlDataAdapter sda;
29        DataTable dt;
30        void getData()
31        {
32            //Northwind database download path:http://download.csdn.net/down/845087/beyondchina123
33            //init sqlconnection
34            SqlConnectionStringBuilder connbuilder = new SqlConnectionStringBuilder();
35            connbuilder.DataSource = ".";//本地服務器
36            connbuilder.IntegratedSecurity = true;//Windows集成驗證
37            connbuilder.InitialCatalog = "Northwind";//數據庫為Northwind
38            SqlConnection conn = new SqlConnection(connbuilder.ConnectionString);
39            sda = new SqlDataAdapter("select EmployeeID,FirstName,LastName,Address from Employees ", conn);
40            SqlCommandBuilder commbuilder = new SqlCommandBuilder(sda);
41            dt = new DataTable();
42            sda.Fill(dt);
43            listview1.ItemsSource = dt.DefaultView;
44        }
45      }
46}
47
48

     本文主要簡單介紹了GridPattern以及GridPattern在測試中是使用方法。

使用UI Automation實現自動化測試--4.9 (ScrollPattern)

ScrollPattern

ScrollPattern是用來操作控件的滾動條,目前支持ScrollPattern的控件有ListBoxlistViewGridViewTreeView.

ScrollPattern主要方法

  1. 1.         Scroll 水平和垂直滾動內容區域的可見區域滾動, Scroll有兩個參數,其類型為ScrollAmount枚舉類型。
  2. 2.         ScrollHorizontal 按指定的 ScrollAmount 水平滾動內容區域的當前可見區域滾動。
  3. 3.         ScrollVertical 按指定的 ScrollAmount 垂直滾動內容區域的當前可見區域滾動。

ScrollPattern屬性

 

  1. VerticallyScrollable 屬性用於判定是否可以垂直滾動。
  2. HorizontallyScrollable 屬性用於判定是否可以水平滾動。
  3. HorizontalScrollPercent 獲取當前水平滾動條的位置。
  4. VerticalScrollPercent 獲取當前垂直滾動條的位置。

 

下面我們通過一個實例來演示自動化測試中如何使用ScrollPattern來測試GridView中滾動條的方法:

 


  1using System;
  2using System.Text;
  3using System.Diagnostics;
  4using System.Threading;
  5using System.Windows.Automation;
  6
  7namespace UIATest
  8{
  9    class Program
 10    {
 11        static void Main(string[] args)
 12        {
 13            Process process = Process.Start(@"F:\CSharpDotNet\AutomationTest\ATP\WpfApp\bin\Debug\WpfApp.exe");
 14            int processId = process.Id;
 15            Thread.Sleep(1000);
 16
 17            ScrollPattern
 31            
 32        }
 33
 34        /// <summary>
 35        /// Get the automation elemention of current form.
 36        /// </summary>
 37        /// <param name="processId">Process Id</param>
 38        /// <returns>Target element</returns>
 39        public static AutomationElement FindWindowByProcessId(int processId)
 40        {
 41            AutomationElement targetWindow = null;
 42            int count = 0;
 43            try
 44            {
 45                Process p = Process.GetProcessById(processId);
 46                targetWindow = AutomationElement.FromHandle(p.MainWindowHandle);
 47                return targetWindow;
 48            }
 49            catch (Exception ex)
 50            {
 51                count++;
 52                StringBuilder sb = new StringBuilder();
 53                string message = sb.AppendLine(string.Format("Target window is not existing.try #{0}", count)).ToString();
 54                if (count > 5)
 55                {
 56                    throw new InvalidProgramException(message, ex);
 57                }
 58                else
 59                {
 60                    return FindWindowByProcessId(processId);
 61                }
 62            }
 63        }
 64
 65
 66        /// <summary>
 67        /// Get the automation element by automation Id.
 68        /// </summary>
 69        /// <param name="windowName">Window name</param>
 70        /// <param name="automationId">Control automation Id</param>
 71        /// <returns>Automatin element searched by automation Id</returns>
 72        public static AutomationElement FindElementById(int processId, string automationId)
 73        {
 74            AutomationElement aeForm = FindWindowByProcessId(processId);
 75            AutomationElement tarFindElement = aeForm.FindFirst(TreeScope.Descendants,
 76            new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
 77            return tarFindElement;
 78        }
 79
 80        GetScrollPattern helper
 98    }
 99}
100

 

   XAML源碼:

 


 1<Window x:Class="WpfApp.GridView"
 2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4    Title="GridView" Height="280" Width="467">
 5    <Grid>
 6        <!--將鼠標放在方框的邊緣點擊就會產生相應的分割線生成Grid.RowDefinitions-->
 7        <Grid.RowDefinitions>
 8            <!--Auto,實際作用就是取實際控件所需的最小值;值為*或N*,實際作用就是取盡可能大的值;數字,絕對尺寸-->
 9            <RowDefinition Height="*" />
10            <RowDefinition Height="auto" MinHeight="95" />
11            <RowDefinition Height="22" />
12        </Grid.RowDefinitions>
13        <ListView Name="listview1" MinWidth="280" Grid.RowSpan="2" MouseMove="listview1_MouseMove">
14            <ListView.View>
15                <GridView x:Name="gridView1">
16                    <GridViewColumn Header="EmployeeID" DisplayMemberBinding="{Binding Path=EmployeeID}"></GridViewColumn>
17                    <GridViewColumn Header="FirstName" DisplayMemberBinding="{Binding Path=FirstName}"></GridViewColumn>
18                    <GridViewColumn Header="LastName" DisplayMemberBinding="{Binding Path=LastName}"></GridViewColumn>
19                    <GridViewColumn Header="Address" DisplayMemberBinding="{Binding Path=Address}"></GridViewColumn>
20                </GridView>
21            </ListView.View>
22        </ListView>
23        <!--Grid.Row="1"用來設置WrapPanel及Button應該在父容器的什么位置-->
24    </Grid>
25
26</Window>

       后台CS源碼:

 


 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Text;
 5using System.Windows;
 6using System.Windows.Controls;
 7using System.Windows.Data;
 8using System.Windows.Documents;
 9using System.Windows.Input;
10using System.Windows.Media;
11using System.Windows.Media.Imaging;
12using System.Windows.Shapes;
13using System.Data.SqlClient;
14using System.Data;
15
16namespace WpfApp
17{
18    /// <summary>
19    /// Interaction logic for GridView.xaml
20    /// </summary>
21    public partial class GridView : Window
22    {
23        public GridView()
24        {
25            InitializeComponent();
26            getData();
27        }
28        SqlDataAdapter sda;
29        DataTable dt;
30        void getData()
31        {
32            //init sqlconnection
33            SqlConnectionStringBuilder connbuilder = new SqlConnectionStringBuilder();
34            connbuilder.DataSource = ".";//本地服務器
35            connbuilder.IntegratedSecurity = true;//Windows集成驗證
36            connbuilder.InitialCatalog = "TestDB";//數據庫為Northwind
37            SqlConnection conn = new SqlConnection(connbuilder.ConnectionString);
38            sda = new SqlDataAdapter("select EmployeeID,FirstName,LastName,Address from Employees ", conn);
39            SqlCommandBuilder commbuilder = new SqlCommandBuilder(sda);
40            //sda.UpdateCommand = commbuilder.GetUpdateCommand();
41            dt = new DataTable();
42            //sda.AcceptChangesDuringUpdate = true;
43            sda.Fill(dt);
44            listview1.ItemsSource = dt.DefaultView;
45        }
46    }
47}
48
49

       數據庫及數據庫表源碼:

 


 1USE [master]
 2GO
 3/****** Object:  Database TestDB    Script Date: 10/17/2009 16:08:09 ******/
 4IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'TestDB')
 5DROP DATABASE [TestDB]
 6CREATE DATABASE TestDB ON  PRIMARY 
 7( NAME = N'TestDB', FILENAME = N'C:\TestDB.mdf' , SIZE = 2688KB , MAXSIZE = UNLIMITED, FILEGROWTH = 80KB )
 8 LOG ON 
 9( NAME = N'TestDB_log', FILENAME = N'C:\TestDB.ldf' , SIZE = 1024KB , MAXSIZE = UNLIMITED, FILEGROWTH = 10%)
10GO
11
12use TestDB
13
14CREATE TABLE [dbo].[Employees](
15    [EmployeeID] [int] IDENTITY(1,1) primary key NOT NULL,
16    [LastName] [varchar](20) NOT NULL,
17    [FirstName] [varchar](10) NOT NULL,
18    [Address] [varchar](60) NULL
19) 
20
21GO
22truncate table employees
23declare @i int
24set @i = 1
25while @i<25
26begin
27
28insert into Employees
29(
30   LastName,
31   FirstName,
32   [Address]
33) 
34values
35('Kaden'+cast(@i as varchar), 'Kang'+cast(@i as varchar), 'Nanjing, Jiangsu, China'+cast(@i as varchar))
36set @i=@i+1
37end
38
39

        本文簡單介紹了ScrollPattern以及使用ScrollPattern來操作垂直水平滾動條。

 

 

 

 

 

http://www.cnblogs.com/kangyi/archive/2009/09/10/1564122.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM