在运行时在Xamarin.Forms中访问DataTemplate内部的视图

时间:2018-03-19 23:24:10

标签: xamarin.forms datatemplate

我想知道是否有办法在Xamarin.Forms的ListView中获取对DataTemplate内部视图的引用。 假设我有这个xaml:

<ListView x:Name="ProductList" ItemsSource="{Binding Products}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout BackgroundColor="#eee" x:Name="ProductStackLayout"
                                     Orientation="Vertical" Padding="5" Tapped="ListItemTapped">
                            <Label Text="{Binding Name}" 
                                   Style="{DynamicResource ProductPropertiesStyle}"/>
                            <Label Text="{Binding Notes}" IsVisible="{Binding HasNotes}" 
                                    Style="{DynamicResource NotesStyle}"
                                />
                            <Label Text="{Binding Date}" 
                                   Style="{DynamicResource DateStyle}"
                            />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

我希望能够获取名为&#34; ProductStackLayout&#34;的StackLayout的引用。在ListView的每一行。我需要在页面出现时执行此操作,以动态操作它的内容(对于通过数据绑定无法实现的内容),因此我无法利用传入的视图引用事件处理程序源自DataTemplate本身的元素,如ItemTapped或类似的东西。

据我所知,在WPF或UWP中,可以在VisualTreeHelper类的帮助下实现类似的功能,但我不相信Xamarin.Forms中有相同的类。

2 个答案:

答案 0 :(得分:2)

是的,可以访问在运行时使用DataTemplate创建的视图。来自XAML的BindingContextChanged内的视图的隐藏DataTemplate事件。在回调事件中,可以使用sender参数访问从DataTemplate创建的视图。您需要输入发送者来访问视图,因为发件人被装箱为对象类型。

否则,您可以使用DataTemplate选择器根据您的对象创建视图。

答案 1 :(得分:1)

您还可以这样投射:

    ITemplatedItemsView<Cell> templatedItemsView = listView as ITemplatedItemsView<Cell>;
    ViewCell firstCell = templatedItemsView.TemplatedItems[0] as ViewCell;
    StackLayout stackLayout = firstCell.View as StackLayout;

哪个会给您参考这些观点


但是您可能希望基于绑定上下文的更改做出反应,因为否则您将不得不手动更改视图的内容。

我怀疑使用BindingContextChanged会使您渲染两次内容-首先,更改会导致渲染正常,然后再次渲染。因此,例如,如果发生字符串更改-标签将重新呈现-之后,您将在BindingContextChanged中获取值并执行您实际想要的呈现。

您可以继承ListView的子类,我认为这可以阻止它:

public class CustomListView : ListView
{
    protected override void SetupContent(Cell content, int index)
    {
        // render differently depending on content.BindingContext
        base.SetupContent(content, index);
    }
}