使用UI Automation实现自动化测试--1-4

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

 

 

 

 

 

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

 

 
分类: .NET技术
 
 
posted @   小草旁的大树  阅读(702)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示
CONTENTS

"知识改变人生"