読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

UWPで指定した場所に存在するコントロールを列挙する

マウスカーソルの場所にあるコントロールに対して操作をしたいとかいう結構特殊な要件のときに使えるテクニックです。

VisualTreeHelperクラスのFindElementsInHostCoordinatesメソッドを使うと指定した点(Point)や、領域(Rect)にあるUIElementをとってくることが出来ます。第一引数がPointやRectで場所を指定して、第二引数でターゲットとなるコントロールを指定します。

例えば、右側のListViewにマウスが乗ると、マウスのある場所にあるコントロールの列挙を左側のListViewに表示するコードは以下のようになります。

<Page
    x:Class="App25.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App25"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ListView x:Name="ResultsListView">
        </ListView>
        <ListView x:Name="TargetListView" Grid.Column="1">
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
            <ListViewItem>Item</ListViewItem>
        </ListView>
    </Grid>
</Page>

C#は、PointerMovedでその場所のUIElementをとって文字列化してる。

using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

// 空白ページのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 を参照してください

namespace App25
{
    /// <summary>
    /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            Window.Current.CoreWindow.PointerMoved += CoreWindow_PointerMoved;
        }

        private void CoreWindow_PointerMoved(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.PointerEventArgs args)
        {
            var results = VisualTreeHelper.FindElementsInHostCoordinates(
                args.CurrentPoint.Position,
                this.TargetListView);
            this.ResultsListView.ItemsSource = results.Select(x => x.ToString());
        }
    }
}

実行すると以下のような結果になります。

f:id:okazuki:20160211180336p:plain