DataGridItemAutomationPeer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Automation / Peers / DataGridItemAutomationPeer.cs / 1477467 / DataGridItemAutomationPeer.cs

                            using System; 
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Security; 
using System.Windows;
using System.Windows.Automation; 
using System.Windows.Automation.Provider; 
using System.Windows.Controls;
using System.Windows.Data; 
using MS.Internal.Automation;

namespace System.Windows.Automation.Peers
{ 
    /// 
    /// AutomationPeer for an item in a DataGrid 
    /// This automation peer correspond to a row data item which may not have a visual container 
    /// 
    public sealed class DataGridItemAutomationPeer : ItemAutomationPeer, 
        IInvokeProvider, IScrollItemProvider, ISelectionItemProvider, ISelectionProvider, IItemContainerProvider
    {
        #region Constructors
 
        /// 
        /// AutomationPeer for an item in a DataGrid 
        ///  
        public DataGridItemAutomationPeer(object item, DataGridAutomationPeer dataGridPeer): base(item, dataGridPeer)
        { 
            if (item == null)
            {
                throw new ArgumentNullException("item");
            } 

            if (dataGridPeer == null) 
            { 
                throw new ArgumentNullException("dataGridPeer");
            } 

            _item = item;
            _dataGridAutomationPeer = dataGridPeer;
        } 

        #endregion 
 
        #region AutomationPeer Overrides
 
        /////
        protected override AutomationControlType GetAutomationControlTypeCore()
        {
            return AutomationControlType.DataItem; 
        }
 
        /// 
        protected override List GetChildrenCore()
        { 
            AutomationPeer wrapperPeer = GetWrapperPeer();
            if (wrapperPeer != null)
            {
                // We need to update children manually since wrapperPeer is not in the Automation Tree 
                // When containers are recycled the visual (DataGridRow) will point to a new item. ForceEnsureChildren will just refresh children of this peer,
                // unlike UpdateSubtree which would raise property change events and recursively updates entire subtree. 
                // WrapperPeer's children are the peers for DataGridRowHeader, DataGridCells and DataGridRowDetails. 
                wrapperPeer.ForceEnsureChildren();
                List children = wrapperPeer.GetChildren(); 
                return children;
            }

            return GetCellItemPeers(); 
        }
 
        /// 
        protected override string GetClassNameCore()
        { 
            AutomationPeer wrapperPeer = GetWrapperPeer();
            if (wrapperPeer != null)
            {
                return wrapperPeer.GetClassName(); 
            }
            else 
            { 
                ThrowElementNotAvailableException();
            } 
            return string.Empty;
        }

        /// 
        public override object GetPattern(PatternInterface patternInterface)
        { 
            switch (patternInterface) 
            {
                case PatternInterface.Invoke: 
                    if (!this.OwningDataGrid.IsReadOnly)
                    {
                        return this;
                    } 

                    break; 
                case PatternInterface.ScrollItem: 
                case PatternInterface.Selection:
                case PatternInterface.ItemContainer: 
                    return this;
                case PatternInterface.SelectionItem:
                    if (IsRowSelectionUnit)
                    { 
                        return this;
                    } 
 
                    break;
            } 

            return base.GetPattern(patternInterface);
        }
 

        internal override AutomationPeer GetPeerFromPoint(Point point) 
        { 
            if (!IsOffscreen())
            { 
                AutomationPeer rowHeaderAutomationPeer = RowHeaderAutomationPeer;
                if (rowHeaderAutomationPeer != null)
                {
                    // Check DataGridRowHeader first 
                    AutomationPeer found = rowHeaderAutomationPeer.GetPeerFromPoint(point);
                    if (found != null) 
                    { 
                        return found;
                    } 
                }
            }

            return base.GetPeerFromPoint(point); 
        }
 
        #endregion 

        #region IItemContainerProvider 
        IRawElementProviderSimple IItemContainerProvider.FindItemByProperty(IRawElementProviderSimple startAfter, int propertyId, object value)
        {
            ResetChildrenCache();
            // Checks if propertyId is valid else throws ArgumentException to notify it as invalid argument is being passed 
            if (propertyId != 0)
            { 
                if (!SelectorAutomationPeer.IsPropertySupportedByControlForFindItemInternal(propertyId)) 
                {
                    throw new ArgumentException(SR.Get(SRID.PropertyNotSupported)); 
                }
            }

 
            IList columns = OwningDataGrid.Columns;
 
            if (columns != null && columns.Count > 0) 
            {
                DataGridCellItemAutomationPeer startAfterItem = null; 
                if (startAfter != null)
                {
                    // get the peer corresponding to this provider
                    startAfterItem = PeerFromProvider(startAfter) as DataGridCellItemAutomationPeer; 
                }
 
                // startIndex refers to the index of the item just after startAfterItem 
                int startIndex = 0;
                if (startAfterItem != null) 
                {
                    if (startAfterItem.Column == null)
                    {
                        throw new InvalidOperationException(SR.Get(SRID.InavalidStartItem)); 
                    }
 
                    // To find the index of the item in items collection which occurs 
                    // immidiately after startAfterItem.Item
                    startIndex = columns.IndexOf(startAfterItem.Column) + 1; 
                    if (startIndex == 0 || startIndex == columns.Count)
                        return null;
                }
 
                if (propertyId == 0 && startIndex < columns.Count)
                { 
                    return (ProviderFromPeer(GetOrCreateCellItemPeer(columns[startIndex]))); 
                }
 
                DataGridCellItemAutomationPeer currentItemPeer;
                object currentValue = null;
                for (int i = startIndex; i < columns.Count; i++)
                { 
                    currentItemPeer = GetOrCreateCellItemPeer(columns[i]);
                    if (currentItemPeer == null) 
                        continue; 
                    try
                    { 
                        currentValue = SelectorAutomationPeer.GetSupportedPropertyValueInternal(currentItemPeer, propertyId);
                    }
                    catch (Exception ex)
                    { 
                        if (ex is ElementNotAvailableException)
                            continue; 
                    } 

                    if (value == null || currentValue == null) 
                    {
                        // Accept null as value corresponding to the property if it finds an item with null as the value of corresponding property else ignore.
                        if (currentValue == null && value == null)
                            return (ProviderFromPeer(currentItemPeer)); 
                        else
                            continue; 
                    } 

                    // Match is found within the specified criterion of search 
                    if (value.Equals(currentValue))
                        return (ProviderFromPeer(currentItemPeer));
                }
            } 
            return null;
        } 
 
        #endregion IItemContainerProvider
 
        #region IInvokeProvider

        // Invoking DataGrid item should commit the item if it is in edit mode
        // or BeginEdit if item is not in edit mode 
        void IInvokeProvider.Invoke()
        { 
            EnsureEnabled(); 

            AutomationPeer wrapperPeer = GetWrapperPeer(); 
            if (wrapperPeer == null)
            {
                this.OwningDataGrid.ScrollIntoView(_item);
            } 

            bool success = false; 
            UIElement owningRow = GetWrapper(); 
            if (owningRow != null)
            { 
                IEditableCollectionView iecv = (IEditableCollectionView)this.OwningDataGrid.Items;
                if (iecv.CurrentEditItem == _item)
                {
                    success = this.OwningDataGrid.CommitEdit(); 
                }
                else 
                { 
                    if (this.OwningDataGrid.Columns.Count > 0)
                    { 
                        DataGridCell cell = this.OwningDataGrid.TryFindCell(_item, this.OwningDataGrid.Columns[0]);
                        if (cell != null)
                        {
                            this.OwningDataGrid.UnselectAll(); 
                            cell.Focus();
                            success = this.OwningDataGrid.BeginEdit(); 
                        } 
                    }
                } 
            }

            // Invoke on a NewItemPlaceholder row creates a new item.
            // BeginEdit on a NewItemPlaceholder row returns false. 
            if (!success && !IsNewItemPlaceholder)
            { 
                throw new InvalidOperationException(SR.Get(SRID.DataGrid_AutomationInvokeFailed)); 
            }
        } 

        #endregion

        #region IScrollItemProvider 

        void IScrollItemProvider.ScrollIntoView() 
        { 
            this.OwningDataGrid.ScrollIntoView(_item);
        } 

        #endregion

        #region ISelectionItemProvider 

        bool ISelectionItemProvider.IsSelected 
        { 
            get
            { 
                return this.OwningDataGrid.SelectedItems.Contains(_item);
            }
        }
 
        IRawElementProviderSimple ISelectionItemProvider.SelectionContainer
        { 
            get 
            {
                return ProviderFromPeer(_dataGridAutomationPeer); 
            }
        }

        void ISelectionItemProvider.AddToSelection() 
        {
            if (!IsRowSelectionUnit) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.DataGridRow_CannotSelectRowWhenCells));
            } 

            // If item is already selected - do nothing
            if (this.OwningDataGrid.SelectedItems.Contains(_item))
            { 
                return;
            } 
 
            EnsureEnabled();
 
            if (this.OwningDataGrid.SelectionMode == DataGridSelectionMode.Single &&
                this.OwningDataGrid.SelectedItems.Count > 0)
            {
                throw new InvalidOperationException(); 
            }
 
            if (this.OwningDataGrid.Items.Contains(_item)) 
            {
                this.OwningDataGrid.SelectedItems.Add(_item); 
            }
        }

        void ISelectionItemProvider.RemoveFromSelection() 
        {
            if (!IsRowSelectionUnit) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.DataGridRow_CannotSelectRowWhenCells));
            } 

            EnsureEnabled();

            if (this.OwningDataGrid.SelectedItems.Contains(_item)) 
            {
                this.OwningDataGrid.SelectedItems.Remove(_item); 
            } 
        }
 
        void ISelectionItemProvider.Select()
        {
            if (!IsRowSelectionUnit)
            { 
                throw new InvalidOperationException(SR.Get(SRID.DataGridRow_CannotSelectRowWhenCells));
            } 
 
            EnsureEnabled();
 
            this.OwningDataGrid.SelectedItem = _item;
        }

        #endregion 

        #region ISelectionProvider 
 
        bool ISelectionProvider.CanSelectMultiple
        { 
            get
            {
                return this.OwningDataGrid.SelectionMode == DataGridSelectionMode.Extended;
            } 
        }
 
        bool ISelectionProvider.IsSelectionRequired 
        {
            get 
            {
                return false;
            }
        } 

        IRawElementProviderSimple[] ISelectionProvider.GetSelection() 
        { 
            DataGrid dataGrid = this.OwningDataGrid;
            if (dataGrid == null) 
            {
                return null;
            }
 
            int rowIndex = dataGrid.Items.IndexOf(_item);
 
            // If row has selection 
            if (rowIndex > -1 && dataGrid.SelectedCellsInternal.Intersects(rowIndex))
            { 
                List selectedProviders = new List();

                for (int i = 0; i < this.OwningDataGrid.Columns.Count; i++)
                { 
                    // cell is selected
                    if (dataGrid.SelectedCellsInternal.Contains(rowIndex, i)) 
                    { 
                        DataGridColumn column = dataGrid.ColumnFromDisplayIndex(i);
                        DataGridCellItemAutomationPeer peer = GetOrCreateCellItemPeer(column); 
                        if (peer != null)
                        {
                            selectedProviders.Add(ProviderFromPeer(peer));
                        } 
                    }
                } 
 
                if (selectedProviders.Count > 0)
                { 
                    return selectedProviders.ToArray();
                }
            }
 
            return null;
        } 
 
        #endregion
 
        #region Private Methods

        /// 
        /// Realized Columns only 
        /// 
        ///  
        internal List GetCellItemPeers() 
        {
            List children = null; 
            ItemPeersStorage newChildren = new ItemPeersStorage();

            IList childItems = null;
            bool usingItemsHost = false; 
            DataGridRow row = GetWrapper() as DataGridRow;
            if (row != null) 
            { 
                if (row.CellsPresenter != null)
                { 
                    Panel itemHost = row.CellsPresenter.ItemsHost;
                    if (itemHost != null)
                    {
                        childItems = itemHost.Children; 
                        usingItemsHost = true;
                    } 
                } 
            }
 
            if (!usingItemsHost)
            {
                childItems = OwningDataGrid.Columns;
            } 

            if (childItems != null) 
            { 
                children = new List(childItems.Count);
                foreach (object childItem in childItems) 
                {
                    DataGridColumn column = null;
                    if (usingItemsHost)
                    { 
                        column = (childItem as DataGridCell).Column;
                    } 
                    else 
                    {
                        column = childItem as DataGridColumn; 
                    }

                    if (column != null)
                    { 
                        DataGridCellItemAutomationPeer peer = GetOrCreateCellItemPeer(column,/*addParentInfo*/ false );
                        children.Add(peer); 
                        newChildren[column] = peer; 
                    }
                } 
            }

            // Cache children for reuse
            CellItemPeers = newChildren; 
            return children;
        } 
 
        internal DataGridCellItemAutomationPeer GetOrCreateCellItemPeer(DataGridColumn column)
        { 
            return GetOrCreateCellItemPeer(column, /*addParentInfo*/ true);
        }

        ///  
        /// It returns the CellItemAutomationPeer if it exist corresponding to the item otherwise it creates
        /// one and adds the Handle and parent info by calling AddParentInfo. 
        ///  
        /// 
        /// Security Critical - Calls a Security Critical operation AddParentInfo which adds parent peer and provides 
        ///                     security critical Hwnd value for this peer created asynchronously.
        /// SecurityTreatAsSafe - It's being called from this object which is real parent for the item peer.
        /// 
        ///  
        /// only required when creating peers for virtualized cells
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private DataGridCellItemAutomationPeer GetOrCreateCellItemPeer(DataGridColumn column, bool addParentInfo)
        { 
            // try to reuse old peer if it exists either in Current AT or in WeakRefStorage of Peers being sent to Client
            DataGridCellItemAutomationPeer peer = CellItemPeers[column];
            if (peer == null)
            { 
                peer = GetPeerFromWeakRefStorage(column);
                if (peer != null && !addParentInfo) 
                { 
                    // As cached peer is getting used it must be invalidated. addParentInfo check ensures that call is coming from GetChildrenCore
                    peer.AncestorsInvalid = false; 
                    peer.ChildrenValid = false;
                }
            }
 
            if (peer == null)
            { 
                peer = new DataGridCellItemAutomationPeer(_item, column); 
                if (addParentInfo && peer != null)
                { 
                    peer.TrySetParentInfo(this);
                }
            }
 
            //perform hookup so the events sourced from wrapper peer are fired as if from the data item
            AutomationPeer wrapperPeer = peer.OwningCellPeer; 
            if (wrapperPeer != null) 
            {
                wrapperPeer.EventsSource = peer; 
            }

            return peer;
        } 

        // Provides Peer if exist in Weak Reference Storage 
        private DataGridCellItemAutomationPeer GetPeerFromWeakRefStorage(object column) 
        {
            DataGridCellItemAutomationPeer returnPeer = null; 
            WeakReference weakRefEP = WeakRefElementProxyStorage[column];
            if (weakRefEP != null)
            {
                ElementProxy provider = weakRefEP.Target as ElementProxy; 
                if (provider != null)
                { 
                    returnPeer = PeerFromProvider(provider as IRawElementProviderSimple) as DataGridCellItemAutomationPeer; 
                    if (returnPeer == null)
                        WeakRefElementProxyStorage.Remove(column); 
                }
                else
                    WeakRefElementProxyStorage.Remove(column);
 
            }
 
            return returnPeer; 
        }
 
        // Called by DataGridCellItemAutomationPeer
        internal void AddProxyToWeakRefStorage(WeakReference wr, DataGridCellItemAutomationPeer cellItemPeer)
        {
            IList columns = OwningDataGrid.Columns; 
            if (columns != null && columns.Contains(cellItemPeer.Column))
            { 
                if (GetPeerFromWeakRefStorage(cellItemPeer.Column) == null) 
                    WeakRefElementProxyStorage[cellItemPeer.Column] = wr;
            } 
        }

        private void EnsureEnabled()
        { 
            if (!_dataGridAutomationPeer.IsEnabled())
            { 
                throw new ElementNotEnabledException(); 
            }
        } 

        #endregion

        #region Private Properties 

        private bool IsRowSelectionUnit 
        { 
            get
            { 
                return (this.OwningDataGrid != null &&
                    (this.OwningDataGrid.SelectionUnit == DataGridSelectionUnit.FullRow ||
                    this.OwningDataGrid.SelectionUnit == DataGridSelectionUnit.CellOrRowHeader));
            } 
        }
 
        private bool IsNewItemPlaceholder 
        {
            get 
            {
                return (_item == CollectionView.NewItemPlaceholder) || (_item == DataGrid.NewItemPlaceholder);
            }
        } 

        internal AutomationPeer RowHeaderAutomationPeer 
        { 
            get
            { 
                DataGridRowAutomationPeer owningRowPeer = GetWrapperPeer() as DataGridRowAutomationPeer;
                return (owningRowPeer != null) ? owningRowPeer.RowHeaderAutomationPeer : null;
            }
        } 

        private DataGrid OwningDataGrid 
        { 
            get
            { 
                DataGridAutomationPeer gridPeer = _dataGridAutomationPeer as DataGridAutomationPeer;
                return (DataGrid)gridPeer.Owner;
            }
        } 

        ///  
        /// Used to cache realized peers. We donot store references to virtualized peers. 
        /// 
        private ItemPeersStorage CellItemPeers 
        {
            get { return _dataChildren; }

            set { _dataChildren = value; } 
        }
 
        private ItemPeersStorage WeakRefElementProxyStorage 
        {
            get { return _weakRefElementProxyStorage; } 
        }

        #endregion
 
        #region Data
 
        private object _item; 
        private AutomationPeer _dataGridAutomationPeer;
        private ItemPeersStorage _dataChildren = new ItemPeersStorage(); 
        private ItemPeersStorage _weakRefElementProxyStorage = new ItemPeersStorage();


        #endregion 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK