UIAutomation 自动化

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;
  2using System.Diagnostics;
  3using System.Threading;
  4using System.Windows.Automation.Provider;
  5using System.Windows.Automation.Text;
  6using System.Windows.Automation;
  7
  8namespace 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

InvokePattern是UIA中最常用的Pattern之一,WPF和Winform中的button控件都支持InvokePattern。

对InvokePattern的Invoke()方法的调用应立即返回,没有出现阻止情况。但是,此行为完全依赖于 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)

ValuePattern是UI Automation中最常见的Pattern之一,Winform和WPF的TextBox控件都支持ValuePattern。

ValuePattern的一个重要的方法是SetValue,在允许调用 SetValue 之前,控件应将其 IsEnabledProperty 设置为 true 并将其 IsReadOnlyProperty 设置为 false。

通过ValuePattern的Current属性可以获得控件的value和IsReadOnly属性。

实现 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的控件有ListView、ListBox、RadioButton、GridView等。

  1. 1.         SelectionItemPattern的三个重要方法:
  2. 1.         AddToSelection:将当前元素添加到所选项的集合。
  3. 2.         RemoveFromSelection: 从选定项的集合中移除当前元素。
  4. 3.         Select: 取消所有已选中的项,然后选择当前元素。
  5. 2.         SelectionItemPattern的Current属性
    可通过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的控件有CheckBox,TreeView中的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中使用ListView和GridView组合即可得到相应的GridView。

GridPattern的方法

GetItem:此方法有两个参数,即DataGrid的Row和Column。

通过GridPattern的GetItem方法可以获取DataGrid中的某个确定的单元格,进而对单元进行操作。

对单元格的操作主要有以下几个方面:

  1. 1.       编辑单元个中的数据。
  2. 2.       获取单元格中的数据。
  3. 3.       获取单元格中嵌套的AutomationElement(一般使用与自定义控件中)。

GridPattern的属性

GridPattern的Current属性中有如下两个属性:

  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的控件有ListBox,listView,GridView,TreeView.

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来操作垂直水平滚动条。

 

 

 

 

 

 

posted @ 2020-11-09 10:40  左正  阅读(762)  评论(0编辑  收藏  举报