Xamarin Forms 的 GroupHeaderTemplate 中图像触发器的绑定不起作用
Binding of image trigger in the GroupHeaderTemplate of Xamarin Forms not working
这是群组 header 模板。视图模型中图像触发器的绑定不起作用。我想根据分组 header 的点击事件更改图像。当组 header 展开时,图像应为向下箭头,当组 header 折叠时,图像应向上箭头
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell >
<ContentView >
<ContentView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference TheMainPage}, Path=BindingContext.HeaderSelectedCommand}" CommandParameter="{Binding .}" Tapped="TapGestureRecognizer_OnTapped"/>
</ContentView.GestureRecognizers>
<StackLayout Padding="15,12,15,12" Orientation="Horizontal" BackgroundColor="{StaticResource DefaultBackgroundColor}">
<StackLayout Orientation="Vertical" HorizontalOptions="Start">
<Label Text="{Binding Key.EpisodeModel.EpisodeTitle}" FontSize="16" TextColor="Black"/>
<Label Text="{Binding Key.EpisodeModel.Department}" />
<Label Text="{Binding Key.EpisodeModel.PeriodOfEpisode}"/>
</StackLayout>
<Label BackgroundColor="{StaticResource LightAirColor}" Text="{Binding Key.EpisodeModel.DocumentCount}" VerticalOptions="Center" HorizontalOptions="EndAndExpand" FontSize="Medium" TextColor="Black"/>
<Image HeightRequest="15">
<Image.Triggers>
<DataTrigger TargetType="Image" Binding="{Binding headerTappedImage}" Value="true">
<Setter Property="Source" Value="ArrowDown.png"></Setter>
</DataTrigger>
<DataTrigger TargetType="Image" Binding="{Binding headerTappedImage}" Value="false">
<Setter Property="Source" Value="ArrowDown.png"></Setter>
</DataTrigger>
</Image.Triggers>
</Image>
</StackLayout>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
这是我背后的代码
private bool _headerTappedImage;
public bool headerTappedImage
{
get { return _headerTappedImage; }
set { _headerTappedImage = value; OnPropertyChanged("headerTappedImage");}
}
public JournalHistoryViewPage(JournalHistoryPageViewModel journalHistoryPageViewModel) : base(
journalHistoryPageViewModel)
{
headerTappedImage= false;
InitializeComponent();
_journalHistoryPageViewModel = journalHistoryPageViewModel;
DocumentList.RefreshCommand = new Command(RefreshJournalHistoryPage);
}
逻辑没写。但图像应显示在 header 模板中。但它没有显示。这是什么原因?
假设下面LayoutRoot
的BindingContext
与Page
的BindingContext
相同,可以按照问题中的建议使用触发器:
<StackLayout x:Name="LayoutRoot">
<ListView x:Name="listView"
ItemsSource="{Binding ItemsGroups}"
...
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference LayoutRoot},
Path=BindingContext.HeaderSelectedCommand}"
CommandParameter="{Binding .}" />
</StackLayout.GestureRecognizers>
...
<Image BackgroundColor="White">
<Image.Triggers>
<DataTrigger TargetType="Image"
Binding="{Binding IsVisible}" Value="False">
<Setter Property="Source"
Value="{OnPlatform Android=add_black.png, UWP=Assets/add_black.png}" />
</DataTrigger>
<DataTrigger TargetType="Image"
Binding="{Binding IsVisible}" Value="True">
<Setter Property="Source"
Value="{OnPlatform Android=remove_black.png, UWP=Assets/remove_black.png}" />
</DataTrigger>
</Image.Triggers>
</Image>
...
IsVisible
属性 是 Grouping
的一部分,示例实现:
public class Grouping<K, T> : ObservableCollection<T>
{
public K Key { get; private set; }
private bool isVisible;
public bool IsVisible
{
get { return isVisible; }
set
{
isVisible = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsVisible)));
}
}
public Grouping(K key, IEnumerable<T> items)
{
Key = key;
foreach (var item in items)
this.Items.Add(item);
}
}
ItemsGroups
可能在 LayoutRoot
的 BindingContext
的 ViewModel
中定义如下,未显示 ItemViewModel
的定义:
public ObservableCollection<Grouping<string, ItemViewModel>> ItemsGroups { get; set; }
可能会将一组项目添加到 ItemsGroups
:
var keyForGroupA = "A";
var itemsForGroupA = new ObservableCollection<ItemViewModel>();
var item1 = new ItemViewModel();
itemsForGroupA.Add(item1);
var item2 = new ItemViewModel();
itemsForGroupA.Add(item2);
...
ItemsGroups.Add(new Grouping<string, ItemViewModel>(keyForGroupA, itemsForGroupA);
HeaderSelectedCommand
的示例实现:
// in constructor:
HeaderSelectedCommand = new Command(p => HeaderSelectedCommandExecute(p));
// property
public ICommand HeaderSelectedCommand { get; private set; }
// action
void HeaderSelectedCommandExecute(object p)
{
var grp = (Grouping<string, ItemViewModel>)p;
grp.IsVisible = !grp.IsVisible;
}
这是群组 header 模板。视图模型中图像触发器的绑定不起作用。我想根据分组 header 的点击事件更改图像。当组 header 展开时,图像应为向下箭头,当组 header 折叠时,图像应向上箭头
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell >
<ContentView >
<ContentView.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference TheMainPage}, Path=BindingContext.HeaderSelectedCommand}" CommandParameter="{Binding .}" Tapped="TapGestureRecognizer_OnTapped"/>
</ContentView.GestureRecognizers>
<StackLayout Padding="15,12,15,12" Orientation="Horizontal" BackgroundColor="{StaticResource DefaultBackgroundColor}">
<StackLayout Orientation="Vertical" HorizontalOptions="Start">
<Label Text="{Binding Key.EpisodeModel.EpisodeTitle}" FontSize="16" TextColor="Black"/>
<Label Text="{Binding Key.EpisodeModel.Department}" />
<Label Text="{Binding Key.EpisodeModel.PeriodOfEpisode}"/>
</StackLayout>
<Label BackgroundColor="{StaticResource LightAirColor}" Text="{Binding Key.EpisodeModel.DocumentCount}" VerticalOptions="Center" HorizontalOptions="EndAndExpand" FontSize="Medium" TextColor="Black"/>
<Image HeightRequest="15">
<Image.Triggers>
<DataTrigger TargetType="Image" Binding="{Binding headerTappedImage}" Value="true">
<Setter Property="Source" Value="ArrowDown.png"></Setter>
</DataTrigger>
<DataTrigger TargetType="Image" Binding="{Binding headerTappedImage}" Value="false">
<Setter Property="Source" Value="ArrowDown.png"></Setter>
</DataTrigger>
</Image.Triggers>
</Image>
</StackLayout>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
这是我背后的代码
private bool _headerTappedImage;
public bool headerTappedImage
{
get { return _headerTappedImage; }
set { _headerTappedImage = value; OnPropertyChanged("headerTappedImage");}
}
public JournalHistoryViewPage(JournalHistoryPageViewModel journalHistoryPageViewModel) : base(
journalHistoryPageViewModel)
{
headerTappedImage= false;
InitializeComponent();
_journalHistoryPageViewModel = journalHistoryPageViewModel;
DocumentList.RefreshCommand = new Command(RefreshJournalHistoryPage);
}
逻辑没写。但图像应显示在 header 模板中。但它没有显示。这是什么原因?
假设下面LayoutRoot
的BindingContext
与Page
的BindingContext
相同,可以按照问题中的建议使用触发器:
<StackLayout x:Name="LayoutRoot">
<ListView x:Name="listView"
ItemsSource="{Binding ItemsGroups}"
...
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference LayoutRoot},
Path=BindingContext.HeaderSelectedCommand}"
CommandParameter="{Binding .}" />
</StackLayout.GestureRecognizers>
...
<Image BackgroundColor="White">
<Image.Triggers>
<DataTrigger TargetType="Image"
Binding="{Binding IsVisible}" Value="False">
<Setter Property="Source"
Value="{OnPlatform Android=add_black.png, UWP=Assets/add_black.png}" />
</DataTrigger>
<DataTrigger TargetType="Image"
Binding="{Binding IsVisible}" Value="True">
<Setter Property="Source"
Value="{OnPlatform Android=remove_black.png, UWP=Assets/remove_black.png}" />
</DataTrigger>
</Image.Triggers>
</Image>
...
IsVisible
属性 是 Grouping
的一部分,示例实现:
public class Grouping<K, T> : ObservableCollection<T>
{
public K Key { get; private set; }
private bool isVisible;
public bool IsVisible
{
get { return isVisible; }
set
{
isVisible = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsVisible)));
}
}
public Grouping(K key, IEnumerable<T> items)
{
Key = key;
foreach (var item in items)
this.Items.Add(item);
}
}
ItemsGroups
可能在 LayoutRoot
的 BindingContext
的 ViewModel
中定义如下,未显示 ItemViewModel
的定义:
public ObservableCollection<Grouping<string, ItemViewModel>> ItemsGroups { get; set; }
可能会将一组项目添加到 ItemsGroups
:
var keyForGroupA = "A";
var itemsForGroupA = new ObservableCollection<ItemViewModel>();
var item1 = new ItemViewModel();
itemsForGroupA.Add(item1);
var item2 = new ItemViewModel();
itemsForGroupA.Add(item2);
...
ItemsGroups.Add(new Grouping<string, ItemViewModel>(keyForGroupA, itemsForGroupA);
HeaderSelectedCommand
的示例实现:
// in constructor:
HeaderSelectedCommand = new Command(p => HeaderSelectedCommandExecute(p));
// property
public ICommand HeaderSelectedCommand { get; private set; }
// action
void HeaderSelectedCommandExecute(object p)
{
var grp = (Grouping<string, ItemViewModel>)p;
grp.IsVisible = !grp.IsVisible;
}