简体   繁体   中英

How can I get the text value of a label that is a child of a stacklayout which is a child of a Frame inside a listview item

I have a Xamarin.Forms PCL VS2015 Solution and have spent three days searching for a solution to my problem. I have tried numerous ways including using the Listview onitemselected which works fine for Win10 but not for Android or iOS. Tried this.FindByName(emailValue); and using the Sender Frame also but no luck. I need to provide the email address which is the label text binding.

<Label x:Name="emailValue"
       Text="{Binding Email}"/>

The label is a child of a child of a listview item.

The x:Name element is not available in the code behind. I understand this is because the label is in a listview and the compiler would not be able to distinguish between the listview items.

I have drilled down using intellisense, on the sender of the Tap ( the Frame) and I can see the Email text that I need but I cant work out a way of extracting it.

    <StackLayout Orientation="Vertical"
           VerticalOptions="FillAndExpand">
<ListView x:Name="listViewContacts"
            ItemSelected="OnListViewItemSelected"
            IsPullToRefreshEnabled="true" Refreshing="OnRefresh"
            SeparatorColor="#FFCF00"
            VerticalOptions="FillAndExpand"
            HasUnevenRows="True">
  <!-- Need HasUnevenRows = true to enable correct 
  display in Android-->
  <ListView.ItemTemplate>
    <DataTemplate >
      <ViewCell>
        <ContentView Padding="5">
          <StackLayout>
            <Grid RowSpacing="10">
              <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
              </Grid.RowDefinitions>
              <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition Width="Auto"/>
              </Grid.ColumnDefinitions>
    <Frame OutlineColor="Black"
                     BackgroundColor="Transparent"
                     Padding="0"
                     Grid.Row="4">
                <Frame.GestureRecognizers>
                  <TapGestureRecognizer Tapped="OnPhoneFrameTapped"/>
                </Frame.GestureRecognizers>
                <StackLayout Orientation="Horizontal"
                              Padding="10,5,0,5">
                  <Label Text="Phone:"/>
                  <Label x:Name="phoneValue"
                         Text="{Binding Mobile}"/>
                </StackLayout>
              </Frame> ...

!

After posting the question I sorted out how to get the text I required using the drill down intellisense for stepping down to the required level.

First level is the Frame. Second level is the Stacklayout and the required Label is third level.

I then use Plugin.Messanger to send the email.

Note this also works for using the phone dialer and extracting the phone number to call.

Here is my solution: Note the listChildren[1] is the index of the child label I require.

void OnEmailFrameTapped(object sender, EventArgs args)
    {
        Frame f = (Frame)sender;
        string emailstring = string.Empty;

        var fcontent = f.Content;

        var myStacklayout = fcontent.GetType();

        if (myStacklayout == typeof (StackLayout))
        {
           StackLayout fStacklayout = (StackLayout)fcontent;

            var listChildren = fStacklayout.Children;

            var reqLabel = listChildren[1];

            var theLabel = reqLabel.GetType();

            if (theLabel == typeof(Label))
            {
               Label emailLabel = (Label)reqLabel;

                emailstring = emailLabel.Text;
            }
        }

        var emailMessenger = CrossMessaging.Current.EmailMessenger;
        if (emailMessenger.CanSendEmail)
        {
            // Send simple e-mail to single receiver without attachments, bcc, cc etc.
            emailMessenger.SendEmail(emailstring,
                "Test Sender",
                "Hello from message");
        }
    }

Using the information that you found, I was also able to narrow the TapGesture to the specific Label I needed which simplified the piece I needed.

Here is the xaml

<Label   
   Text="{Binding MapUri}" 
   TextColor="#ab1e2c" 
   FontAttributes="Bold"
   HorizontalTextAlignment="End">
     <Label.GestureRecognizers>
         <TapGestureRecognizer
             Tapped="OnLabelTapped"
             NumberOfTapsRequired="1" />
    </Label.GestureRecognizers>
</Label>

Here's the .cs

public async void OnLabelTapped(object sender, EventArgs args)
{
    string mapUri = string.Empty;
    Label l = (Label)sender;
    mapUri = l.mapUri; 

    var result = await Application.Current.MainPage.DisplayAlert("Alert", "Launch Google Maps" , "OK", "Cancel");
    if (result)
    {
        Device.OpenUri(new Uri(mapUri));
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM