質問

I've a list of locations the user has saved for future reference (this is for a weather app).

I'm using an ItemsControl to present the list:

            <ItemsControl 
                Grid.Row="0"
                x:Name="locations"
                ItemsSource="{Binding Path=Locations}"
                ItemTemplate="{StaticResource locationRow}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Vertical" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>

This is the ItemTemplate:

            <DataTemplate 
                    x:Key="locationRow">

                    <StackPanel>
                        <TextBlock 
                            x:Name="City"
                            Tap="Location_Tap" 
                            Text="{Binding City}"/>

                        <TextBlock 
                            x:Name="Country"
                            Margin="0,0,0,20"
                            FontSize="20"
                            Tap="Location_Tap" 
                            Text="{Binding Country}"/>
                    </StackPanel>
                </DataTemplate>

Everything displays fine. But I'm having problems identifying the row/location that has been tapped.

What I'd like to do is when either TextBlock for an Item is tapped, to determine the row number of the Item in the Location_Tap event handler so that I know exactly what location was tapped and thereby show the weather for the tapped location. For example, if the tapped item index number is 1, then I know the index of the location tapped is also 1.

Any guidance here would be much appreciated.

Thanks,

Bardi

UPDATE: I followed Pantelis' suggestion and it almost worked. I would get an error:

"Cannot convert lambda expression to type 'MetroApp.LocationDbRecord' because it is not a delegate type"

This error would be in the event handler's second line for the argument of the IndexOf method:

        var sourceObject = ((FrameworkElement)sender).DataContext as LocationDbRecord;
        int index = this.viewModel.Locations.IndexOf(item => item.City == sourceObject.City);

I managed to get the index I'm after however by changing the second line simply to:

int index = this.viewModel.Locations.IndexOf(sourceObject);

So I got the solution I'm after but am still curious why the original suggestion 1) didn't work and 2) was the recommended solution instead of just using the sourceObject as the parameter value (I'm sure there was a good reason!).

役に立ちましたか?

解決

You cannot locate the UIElement (Tapped Item) by index. Your ItemsPanel is a StackPanel which does not support indexing. Instead, you can get the DataContext of the tapped item and its index in your ItemsSource and work with that object.

private void TextBlock_OnTap(object sender, GestureEventArgs e)
{
    var sourceObject = ((FrameworkElement) sender).DataContext as TypeOfLocation;
    int index = ViewModel.Locations.IndexOf(item => item.City == sourceObject.City);
}

In order to get an instance of your ViewModel in your View you can set a public property of your ViewModel in the code-behind class.

public MyViewModel ViewModel
{  
    get { return (MyViewModel) this.DataContext; }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top