Xamarin Forms:从DataTemplate调用ViewModel的命令
Xamarin Forms: Call Command of ViewModel from DataTemplate
我在这里遇到了绑定问题。
我在控件模板中创建了一个可绑定布局:
<ContentView x:Name="SettingsMenu" ControlTemplate="{StaticResource HeaderTemplate}" AbsoluteLayout.LayoutBounds="0.5,0.5,1,1"
AbsoluteLayout.LayoutFlags="All">
<ScrollView Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout x:Name="SettingsStack" BindableLayout.ItemsSource="{Binding Settings}" BindableLayout.ItemTemplateSelector="{StaticResource SettingsSelectorTemplate}" Orientation="Vertical" Spacing="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ScrollView>
</ContentView>
我想做的是在视图模型中调用一个命令。调用在项目模板选择器内部作为 App.xml
内的资源字典
<ResourceDictionary>
<DataTemplate x:Key="PlaceholderSettingsTemplate">
### SOME STUFF
</DataTemplate>
<DataTemplate x:Key="HeaderSettingsTemplate">
### SOME STUFF
<Grid ...>
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="ButtonClick" Command="{Binding BindingContext.SettingsTap, Source={x:Reference SettingsPage}}" CommandParameter="{Binding}" /> ########## <--------- WHAT TO USE FOR SOURCE?
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
<data:SettingsSelector x:Key="SettingsSelectorTemplate" Placeholder="{StaticResource PlaceholderSettingsTemplate}" Heading="{StaticResource HeaderSettingsTemplate}" Content="{StaticResource ContentSettingsTemplate}" />
</ResourceDictionary>
在我将它移动到 App.xml 文件的资源字典中之前,我只是使用了父 Contentview 的 x:Name。但是:我不能再按名称引用它了,因为我将它移到了 App.xml.
中的资源字典中
现在,答案可能微不足道,但我就是找不到解决方案。
感谢任何帮助。
亲切的问候
您可以使用包含所有内容的数据模板的网格找到 SettingsStack
StackLayout。由于 SettingsStack
与父内容视图具有相同的绑定上下文,您可以在 App.cs 中访问绑定上下文,例如:
<DataTemplate x:Key="HeaderSettingsTemplate">
<!--### SOME STUFF-->
<Grid x:Name="ParentGrid">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Parent.BindingContext.SettingsTap, Source={x:Reference ParentGrid}}" CommandParameter="{Binding}" />
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
ParentGrid
的父级在您的当前页面上 SettingsStack
。
从项目模板(即使它在不同的文件中),您可以使用以下方法访问它的祖先的视图模型:
Command="{Binding Source={RelativeSource AncestorType={x:Type SettingsViewModel}}, Path=SettingsTap}" CommandParameter="{Binding}"
在这种情况下,我假设祖先的视图模型的名称是 SettingsViewModel,但您明白了。
这是一篇关于相对绑定的有趣文章,它也描述了其他场景:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings#bind-to-an-ancestor
干杯。
换一种方式我们可以直接使用ContentPage
作为AncestorType
。然后用 BindingContext
.
绑定命令
{Binding BindingContext.SomeCommand, Source={RelativeSource AncestorType={x:Type ContentPage}}}
完整示例
<DragGestureRecognizer
DragStartingCommand="{Binding BindingContext.SomeCommand, Source={RelativeSource AncestorType={x:Type ContentPage}}}"
DragStartingCommandParameter="{Binding}"/>
这种方式也适用于单独的资源文件(例如 MySeparateResource.xml -> MyPageView.xaml)。
我在这里遇到了绑定问题。
我在控件模板中创建了一个可绑定布局:
<ContentView x:Name="SettingsMenu" ControlTemplate="{StaticResource HeaderTemplate}" AbsoluteLayout.LayoutBounds="0.5,0.5,1,1"
AbsoluteLayout.LayoutFlags="All">
<ScrollView Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout x:Name="SettingsStack" BindableLayout.ItemsSource="{Binding Settings}" BindableLayout.ItemTemplateSelector="{StaticResource SettingsSelectorTemplate}" Orientation="Vertical" Spacing="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ScrollView>
</ContentView>
我想做的是在视图模型中调用一个命令。调用在项目模板选择器内部作为 App.xml
内的资源字典<ResourceDictionary>
<DataTemplate x:Key="PlaceholderSettingsTemplate">
### SOME STUFF
</DataTemplate>
<DataTemplate x:Key="HeaderSettingsTemplate">
### SOME STUFF
<Grid ...>
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="ButtonClick" Command="{Binding BindingContext.SettingsTap, Source={x:Reference SettingsPage}}" CommandParameter="{Binding}" /> ########## <--------- WHAT TO USE FOR SOURCE?
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
<data:SettingsSelector x:Key="SettingsSelectorTemplate" Placeholder="{StaticResource PlaceholderSettingsTemplate}" Heading="{StaticResource HeaderSettingsTemplate}" Content="{StaticResource ContentSettingsTemplate}" />
</ResourceDictionary>
在我将它移动到 App.xml 文件的资源字典中之前,我只是使用了父 Contentview 的 x:Name。但是:我不能再按名称引用它了,因为我将它移到了 App.xml.
中的资源字典中现在,答案可能微不足道,但我就是找不到解决方案。
感谢任何帮助。
亲切的问候
您可以使用包含所有内容的数据模板的网格找到 SettingsStack
StackLayout。由于 SettingsStack
与父内容视图具有相同的绑定上下文,您可以在 App.cs 中访问绑定上下文,例如:
<DataTemplate x:Key="HeaderSettingsTemplate">
<!--### SOME STUFF-->
<Grid x:Name="ParentGrid">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Parent.BindingContext.SettingsTap, Source={x:Reference ParentGrid}}" CommandParameter="{Binding}" />
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
ParentGrid
的父级在您的当前页面上 SettingsStack
。
从项目模板(即使它在不同的文件中),您可以使用以下方法访问它的祖先的视图模型:
Command="{Binding Source={RelativeSource AncestorType={x:Type SettingsViewModel}}, Path=SettingsTap}" CommandParameter="{Binding}"
在这种情况下,我假设祖先的视图模型的名称是 SettingsViewModel,但您明白了。
这是一篇关于相对绑定的有趣文章,它也描述了其他场景:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings#bind-to-an-ancestor
干杯。
换一种方式我们可以直接使用ContentPage
作为AncestorType
。然后用 BindingContext
.
{Binding BindingContext.SomeCommand, Source={RelativeSource AncestorType={x:Type ContentPage}}}
完整示例
<DragGestureRecognizer
DragStartingCommand="{Binding BindingContext.SomeCommand, Source={RelativeSource AncestorType={x:Type ContentPage}}}"
DragStartingCommandParameter="{Binding}"/>
这种方式也适用于单独的资源文件(例如 MySeparateResource.xml -> MyPageView.xaml)。