Xamarin 表单:如何仅为 Collectionview 中的选定项目添加下划线
Xamarin forms: How to add an underline only for the selected item in Collectionview
我有一个 horizontal collectionview
和一些项目,我只需要为所选项目添加下划线。
我试过如下:
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public List<Category> categoryList { get; set; }
public MainPage()
{
InitializeComponent();
categoryList = new List<Category>();
SetItems(true, false, false, false, false, false);
}
private void SetItems(bool v1, bool v2, bool v3, bool v4, bool v5, bool v6)
{
categoryList.Add(new Category() { Title = "itme1", IsSelected = v1 });
categoryList.Add(new Category() { Title = "itme2", IsSelected = v2 });
categoryList.Add(new Category() { Title = "itme3", IsSelected = v3 });
categoryList.Add(new Category() { Title = "itme4", IsSelected = v4 });
categoryList.Add(new Category() { Title = "itme5", IsSelected = v5 });
categoryList.Add(new Category() { Title = "itme6", IsSelected = v6 });
Category_collectionview.ItemsSource = categoryList;
}
public void CategoryTapped(object sender, SelectionChangedEventArgs e)
{
var selectedItem = (e.CurrentSelection.FirstOrDefault() as Category);
if (selectedItem != null)
{
if (selectedItem.Title == "itme1")
{
SetItems(true, false, false, false, false, false);
}
else if (selectedItem.Title == "itme2")
{
SetItems(false, true, false, false, false, false);
}
else if (selectedItem.Title == "itme3")
{
SetItems(false, false, true, false, false, false);
}
}
Category_collectionview.SelectedItem = null;
}
}
public class Category
{
public string Title { get; set; }
public bool IsSelected { get; set; }
}
MainPage.xaml
<CollectionView
SelectionMode="Single"
SelectionChanged="CategoryTapped"
x:Name="Category_collectionview"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout
Orientation="Vertical"
Margin="5">
<Label
TextColor="Black"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
Text="{Binding Title}">
<Label.FontSize>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>16</OnIdiom.Phone>
<OnIdiom.Tablet>32</OnIdiom.Tablet>
<OnIdiom.Desktop>16</OnIdiom.Desktop>
</OnIdiom>
</Label.FontSize>
</Label>
<BoxView
HorizontalOptions="FillAndExpand"
BackgroundColor="Black"
IsVisible="{Binding IsSelected}"
HeightRequest="2"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
但是 boxview
总是在第一项上,我在这里缺少什么?
您需要在模型中实现接口 INotifyPropertyChanged,以便您可以在运行时更新 UI
public class Category : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string Title { get; set; }
bool isSelected;
public bool IsSelected { get {
return isSelected;
}
set
{
if(value!= isSelected)
{
isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
}
此外,CategoryTapped 事件对您的情况无效。您可以使用 TapGestureRecognizer
<CollectionView
SelectionMode="Single"
x:Name="Category_collectionview"
ItemsSource="{Binding categoryList}"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout
Orientation="Vertical"
Margin="5">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</StackLayout.GestureRecognizers>
//...
在后面的代码中
注意: 最好使用 ObservableCollection 而不是 List
。而且每次都重新设置 ItemsSource 并不是一个好的设计。
public partial class MainPage : ContentPage
{
public ObservableCollection<Category> categoryList { get; set; }
public MainPage()
{
InitializeComponent();
categoryList = new ObservableCollection<Category>();
SetItems(true, true, false, false, false, false);
BindingContext = this;
}
private void SetItems(bool v1, bool v2, bool v3, bool v4, bool v5, bool v6)
{
categoryList.Add(new Category() { Title = "itme1", IsSelected = v1 });
categoryList.Add(new Category() { Title = "itme2", IsSelected = v2 });
categoryList.Add(new Category() { Title = "itme3", IsSelected = v3 });
categoryList.Add(new Category() { Title = "itme4", IsSelected = v4 });
categoryList.Add(new Category() { Title = "itme5", IsSelected = v5 });
categoryList.Add(new Category() { Title = "itme6", IsSelected = v6 });
Category_collectionview.ItemsSource = categoryList;
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
var obj = sender as StackLayout;
var currentItems = obj.BindingContext as Category;
foreach (Category category in categoryList)
{
category.IsSelected = false;
if (currentItems == category)
{
category.IsSelected = true;
}
}
Category_collectionview.SelectedItem = null;
}
}
我有一个 horizontal collectionview
和一些项目,我只需要为所选项目添加下划线。
我试过如下:
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public List<Category> categoryList { get; set; }
public MainPage()
{
InitializeComponent();
categoryList = new List<Category>();
SetItems(true, false, false, false, false, false);
}
private void SetItems(bool v1, bool v2, bool v3, bool v4, bool v5, bool v6)
{
categoryList.Add(new Category() { Title = "itme1", IsSelected = v1 });
categoryList.Add(new Category() { Title = "itme2", IsSelected = v2 });
categoryList.Add(new Category() { Title = "itme3", IsSelected = v3 });
categoryList.Add(new Category() { Title = "itme4", IsSelected = v4 });
categoryList.Add(new Category() { Title = "itme5", IsSelected = v5 });
categoryList.Add(new Category() { Title = "itme6", IsSelected = v6 });
Category_collectionview.ItemsSource = categoryList;
}
public void CategoryTapped(object sender, SelectionChangedEventArgs e)
{
var selectedItem = (e.CurrentSelection.FirstOrDefault() as Category);
if (selectedItem != null)
{
if (selectedItem.Title == "itme1")
{
SetItems(true, false, false, false, false, false);
}
else if (selectedItem.Title == "itme2")
{
SetItems(false, true, false, false, false, false);
}
else if (selectedItem.Title == "itme3")
{
SetItems(false, false, true, false, false, false);
}
}
Category_collectionview.SelectedItem = null;
}
}
public class Category
{
public string Title { get; set; }
public bool IsSelected { get; set; }
}
MainPage.xaml
<CollectionView
SelectionMode="Single"
SelectionChanged="CategoryTapped"
x:Name="Category_collectionview"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout
Orientation="Vertical"
Margin="5">
<Label
TextColor="Black"
HorizontalTextAlignment="Center"
VerticalTextAlignment="Center"
Text="{Binding Title}">
<Label.FontSize>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>16</OnIdiom.Phone>
<OnIdiom.Tablet>32</OnIdiom.Tablet>
<OnIdiom.Desktop>16</OnIdiom.Desktop>
</OnIdiom>
</Label.FontSize>
</Label>
<BoxView
HorizontalOptions="FillAndExpand"
BackgroundColor="Black"
IsVisible="{Binding IsSelected}"
HeightRequest="2"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
但是 boxview
总是在第一项上,我在这里缺少什么?
您需要在模型中实现接口 INotifyPropertyChanged,以便您可以在运行时更新 UI
public class Category : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string Title { get; set; }
bool isSelected;
public bool IsSelected { get {
return isSelected;
}
set
{
if(value!= isSelected)
{
isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
}
此外,CategoryTapped 事件对您的情况无效。您可以使用 TapGestureRecognizer
<CollectionView
SelectionMode="Single"
x:Name="Category_collectionview"
ItemsSource="{Binding categoryList}"
ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout
Orientation="Vertical"
Margin="5">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</StackLayout.GestureRecognizers>
//...
在后面的代码中
注意: 最好使用 ObservableCollection 而不是 List
。而且每次都重新设置 ItemsSource 并不是一个好的设计。
public partial class MainPage : ContentPage
{
public ObservableCollection<Category> categoryList { get; set; }
public MainPage()
{
InitializeComponent();
categoryList = new ObservableCollection<Category>();
SetItems(true, true, false, false, false, false);
BindingContext = this;
}
private void SetItems(bool v1, bool v2, bool v3, bool v4, bool v5, bool v6)
{
categoryList.Add(new Category() { Title = "itme1", IsSelected = v1 });
categoryList.Add(new Category() { Title = "itme2", IsSelected = v2 });
categoryList.Add(new Category() { Title = "itme3", IsSelected = v3 });
categoryList.Add(new Category() { Title = "itme4", IsSelected = v4 });
categoryList.Add(new Category() { Title = "itme5", IsSelected = v5 });
categoryList.Add(new Category() { Title = "itme6", IsSelected = v6 });
Category_collectionview.ItemsSource = categoryList;
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
var obj = sender as StackLayout;
var currentItems = obj.BindingContext as Category;
foreach (Category category in categoryList)
{
category.IsSelected = false;
if (currentItems == category)
{
category.IsSelected = true;
}
}
Category_collectionview.SelectedItem = null;
}
}