質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

Q&A

解決済

2回答

3275閲覧

Xamarin.FormのGridにC#コード側からタップイベントを追加するのは可能か

hiyonit

総合スコア6

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

Xamarin

Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

0グッド

0クリップ

投稿2020/09/22 09:12

編集2020/09/22 09:14

Xamarin.FormおよびC#初心者です。
初歩的なところで詰まっているのかもしれませんが、お力をお貸しください。

前提・実現したいこと

商品一覧画面から任意の商品行をタップ/ロングタップで別画面に遷移、というアプリを作っています。

最終的に実現したいことは、商品行をタップ/ロングタップした場合にそれぞれ異なるイベントを紐づけること、です。
以下ページを参考にジェスチャの設定をしようとしています。
https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/app-fundamentals/gestures/tap
https://www.buildinsider.net/mobile/xamarintips/0035

現在、XAMLでタップイベントを追加することは出来ているのですが(以下xamlソースのコメントアウト箇所がそれに当たります)
ロングタップの方はカスタムレンダラーを使ってC#で実装するしかなさそうだったので、
それであればタップもC#側で実装できないかなと思い試してみたところ、うまくいきません。

何か自分が見落としているところなどあれば、教えていただけないでしょうか。
よろしくお願いいたします。
(Gridに対してC#側で紐づけが難しければ、タップはXamlで実装、ロングタップは実装を断念するつもりです。)

該当のソースコード

以下ソースで実際にデバッグしたとき、一覧の任意の商品をタップしても無反応の状態。

C#

1 var grid = new Grid(); 2 var tapGestureRecognizer = new TapGestureRecognizer(); 3 tapGestureRecognizer.Tapped += (s, e) => { 4 ListBodyList_ItemTapped(s,e); 5 }; 6 grid.GestureRecognizers.Add(tapGestureRecognizer);

Xaml

1 <ScrollView x:Name="MyScrollView" 2 Style="{StaticResource MyScrollView}"> 3 <!--一覧--> 4 <StackLayout x:Name="ListBodyList" 5 BindableLayout.ItemsSource="{Binding _BodyList}" 6 Orientation="Vertical"> 7 <BindableLayout.ItemTemplate> 8 <DataTemplate> 9 <Grid RowSpacing="0" 10 BackgroundColor="{Binding BodyStatusColor}" 11 HeightRequest="80" 12 Margin="0" 13 Padding="0"> 14 <!--<Grid.GestureRecognizers> 15 <TapGestureRecognizer Tapped="ListBodyList_ItemTapped"></TapGestureRecognizer> 16 </Grid.GestureRecognizers>--> 17 <Grid.ColumnDefinitions> 18 <ColumnDefinition Width="*" /> 19 <ColumnDefinition Width="130" /> 20 </Grid.ColumnDefinitions> 21 <Grid.RowDefinitions> 22 <RowDefinition Height="25" /> 23 <RowDefinition Height="*" /> 24 </Grid.RowDefinitions> 25 <Label Grid.Row="0" Grid.Column="0" 26 Text="{Binding ShoCd, StringFormat=' {0:00000} '}" 27 Style="{StaticResource lblShoCd}" /> 28 ...(一部省略)... 29 <Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" 30 Text="{Binding ShoName}" 31 Style="{StaticResource lblShoNm}" 32 LineBreakMode="CharacterWrap" /> 33 </Grid> 34 </DataTemplate> 35 </BindableLayout.ItemTemplate> 36 </StackLayout> 37

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

StackLayoutChildrenプロパティで子のView(Grid)を取得できるので、そのViewに対して、TapGestureRecognizerを追加すればいいです。(BindingContextの設定は、この処理の前に行なっておいてください)

C#

1foreach (var view in ListBodyList.Children) 2{ 3 var tapGestureRecognizer = new TapGestureRecognizer(); 4 tapGestureRecognizer.Tapped += (s, e) => { 5 ListBodyList_ItemTapped(s,e); 6 }; 7 view.GestureRecognizers.Add(tapGestureRecognizer); 8}

また、ロングタップを実装するのであれば、XamarinFormsGestureなどのライブラリがあるので、利用を検討してみてもいいかもしれません。

投稿2020/09/22 12:00

編集2020/09/22 18:37
f-miyu

総合スコア1625

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiyonit

2020/09/23 04:40

f-miyuさん ご回答いただきありがとうございます! ご提示いただいた内容で無事にタップイベントをC#側から実装することが叶いました。 試行錯誤中にStackLayoutにタップを仕込むことは出来ていたのですが、その子に対して設定するという発想に至れませんでした。 とてもシンプルで明快な回答です! 本質問のベストアンサーにさせていただきます。本当にありがとうございました。 ※おすすめいただいたXamarinFormsGesture、拝見しました。  世の名にはこんな便利なライブラリもあったのですね。  諸事情で今回外部ライブラリをnuget導入できないのが惜しいです・・もう少し頑張ってみます!
guest

0

DataTemplateの中身箇所をContentViewとして切り出せば、XAMLで名前を付けていたコントロールをコードビハインドから参照可能のようです。
動作確認のために適当なPersonクラスを別途作って当てはめてますので、その辺りは適宜読み替えてください。
下記に記していないものは生成時から変更はないです。

MainPage.xaml

XAML

1<?xml version="1.0" encoding="utf-8" ?> 2<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 4 x:Class="BlankApp2.Views.MainPage" 5 xmlns:views="clr-namespace:BlankApp2.Views" 6 Title="{Binding Title}"> 7 8 <ScrollView> 9 <StackLayout BindableLayout.ItemsSource="{Binding Persons}" Orientation="Vertical"> 10 <BindableLayout.ItemTemplate> 11 <DataTemplate> 12 <views:DataTemplateArea /> 13 </DataTemplate> 14 </BindableLayout.ItemTemplate> 15 </StackLayout> 16 </ScrollView> 17 18</ContentPage>

DataTemplateArea.xaml

XAML

1<?xml version="1.0" encoding="utf-8" ?> 2<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 3 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 4 xmlns:prism="http://prismlibrary.com" 5 prism:ViewModelLocator.AutowireViewModel="True" 6 x:Class="BlankApp2.Views.DataTemplateArea"> 7 8 <Grid x:Name="Hoge"> 9 <Grid.ColumnDefinitions> 10 <ColumnDefinition Width="*" /> 11 <ColumnDefinition Width="130" /> 12 </Grid.ColumnDefinitions> 13 <Grid.RowDefinitions> 14 <RowDefinition Height="25" /> 15 <RowDefinition Height="*" /> 16 </Grid.RowDefinitions> 17 <Label Grid.Row="0" Grid.Column="0" Text="{Binding Name1}" /> 18 <Label Grid.Row="0" Grid.Column="1" Text="{Binding Price1}" /> 19 <Label Grid.Row="1" Grid.Column="0" Text="{Binding Name2}" /> 20 <Label Grid.Row="1" Grid.Column="1" Text="{Binding Price2}" /> 21 </Grid> 22 23</ContentView>

DataTemplateArea.xaml.cs

C#

1using System; 2using System.Diagnostics; 3using Xamarin.Forms; 4 5namespace BlankApp2.Views 6{ 7 public partial class DataTemplateArea : ContentView 8 { 9 public DataTemplateArea() 10 { 11 InitializeComponent(); 12 13 var tapGestureRecognizer = new TapGestureRecognizer(); 14 tapGestureRecognizer.Tapped += (s, e) => 15 { 16 Debug.WriteLine("Tapped!!!"); 17 }; 18 this.Hoge.GestureRecognizers.Add(tapGestureRecognizer); 19 } 20 } 21}

App.xaml.cs

C#

1using Prism; 2using Prism.Ioc; 3using BlankApp2.ViewModels; 4using BlankApp2.Views; 5using Xamarin.Essentials.Interfaces; 6using Xamarin.Essentials.Implementation; 7using Xamarin.Forms; 8 9namespace BlankApp2 10{ 11 public partial class App 12 { 13 public App(IPlatformInitializer initializer) 14 : base(initializer) 15 { 16 } 17 18 protected override async void OnInitialized() 19 { 20 InitializeComponent(); 21 22 await NavigationService.NavigateAsync("NavigationPage/MainPage"); 23 } 24 25 protected override void RegisterTypes(IContainerRegistry containerRegistry) 26 { 27 containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>(); 28 29 containerRegistry.RegisterForNavigation<NavigationPage>(); 30 containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>(); 31 //containerRegistry.RegisterForNavigation<DataTemplateArea, DataTemplateAreaViewModel>(); 32 // ↑Prismを使用していると勝手に追加されるので削除しましょう 33 } 34 } 35} 36

下記ページがContentView作成で参考になると思います。
Xamarin.Forms で Prism と ReactiveProperty で MVVM な自作コントロールを作りたい(1)

投稿2020/09/22 11:03

takapi_cs

総合スコア349

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiyonit

2020/09/23 04:29

takapi_csさん ご回答いただきありがとうございます! 単純に名前を付けただけではコードビハインドからはうまく呼ぶことが出来ずこの手は諦めておりましたので(本当は呼べて、何かが足りてなかっただけなのかもしれませんが)今回のtakapi_csさんの「タップを仕込みたい部分を外に出す」発想には膝を打ちました。 ご丁寧にサンプルのソースもありがとうございます! とても理解の助けになりました。 (恥ずかしながら提示頂いた内容でPrismなるフレームワークの存在も初めて知りました…) 裏から操作したいものを外出しする、というやり方は他の場合でも応用がききそうなので、 この機会に覚えておきたいと思います。本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問