如何解决点击新项目时折叠 Xamarin ListView 中的所有项目
我遇到了一个看似相对简单的问题,但我无法弄清楚。
我有一个 Xamarin ListView,它使用 ViewCell 的项目模板,如下所示:
<ListView HasUnevenRows="True"
ItemsSource="{Binding Devices}"
ItemTemplate="{StaticResource DeviceDataTemplateSelector}"
SelectionMode="None"
ItemTapped="NewItemTapped"
/>
目前,'DeviceDataTemplateSelector' 始终返回以下 ViewCell(稍后会添加更多 ViewCell)。
ViewCell 使用 Xamarin 社区工具包中的 Expander 控件
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
xmlns:viewmodel="clr-namespace:App.viewmodels"
x:Class="App.UI.ViewCellStandardTemplate">
<ViewCell.View>
<!-- Calls an expander for each ViewCell. -->
<xct:Expander HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Margin="{StaticResource UniversalMargin}"
>
<xct:Expander.Header>
<Grid HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Margin="{StaticResource UniversalMargin}">
<Grid.RowDeFinitions>
<RowDeFinition Height = "*" />
</Grid.RowDeFinitions>
<Grid.ColumnDeFinitions>
<ColumnDeFinition Width = "*" />
</Grid.ColumnDeFinitions>
<Label Grid.Row="0" Grid.Column="0" Text="Header Text" />
</Grid>
</xct:Expander.Header>
<xct:Expander.Content>
<Grid HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Margin="{StaticResource UniversalMargin}">
<Grid.RowDeFinitions>
<RowDeFinition Height = "*" />
</Grid.RowDeFinitions>
<Grid.ColumnDeFinitions>
<ColumnDeFinition Width = "*" />
</Grid.ColumnDeFinitions>
<Button Grid.Row="0"
Grid.Column="0"
Text="Click Me"
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:Pageviewmodel},Mode=FindAncestorBindingContext},Path=ClickCommand}"
CommandParameter="{Binding .}"
/>
</Grid>
</xct:Expander.Content>
</xct:Expander>
</ViewCell.View>
</ViewCell>
到目前为止,所有这些都正常工作 - 问题是当我点击 ListView 中的一个项目时,我希望任何其他展开的项目折叠起来。
换句话说,当我点击 ViewCell 来展开它时,我希望 ListView 中的所有其他 ViewCell 将它们各自的 Expander 控件的“IsExpanded”属性设置为 false。
我曾尝试在 ListView 中调用“ItemTapped”事件,然后在 ListView 中循环遍历元素 - 我不确定这是否是正确的方法?
访问 ViewCell 中 Expander 控件属性的最佳方法是什么?
我不知道该怎么做 - 任何帮助将不胜感激。
谢谢。
解决方法
更新
经过编辑以提供纯 UI 解决方案,灵感来自 get cells from ListView(或可以尝试这个 highlight the selected item)
两步:
- 在 XAML 中将
ViewCell
与ListView
一起定义。
<ListView x:Name="MyList" ...>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<xct:Expander Tapped="Expander_Tapped" ...>
- 在 XAML.cs 中定义方法:
private void Expander_Tapped(object sender,EventArgs e)
{
var expander = sender as Expander;
var state = expander.IsExpanded;
var cells = MyList.GetType().GetRuntimeProperties()
.FirstOrDefault(info => info.Name == "TemplatedItems")?.GetValue(MyList);
if (cells != null) {
foreach (ViewCell cell in cells as ITemplatedItemsList<Cell>)
{
if (cell.BindingContext != null)
{
var child = cell.View as Expander;
child.IsExpanded = false;
}
}
}
expander.IsExpanded = state;
}
上一个答案:
我宁愿在模型类中操作,而不是操作视图属性。
这里的三个步骤:
- 在您的模型类中添加一个布尔属性。
public class YourDeviceModel : INotifyPropertyChanged
{
private bool flag;
public bool Flag
{
get => flag;
set
{
flag = value;
OnPropertyChanged("Flag");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
this.PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(name));
}
}
- 点击时在您的 ViewModel 中定义一个
TapCommand
(如果使用 MVVM)
public ICommand TapCommand => new Command<YourDeviceModel>(OnItemTapped);
private void OnItemTapped(YourDeviceModel currentSelection)
{
//if your Devices is a ObservableCollection,convert it and reset all flags
Devices.ToList().ForEach(x => x.Flag = false);
//set the current one to true
currentSelection.Flag = true;
}
- 在
Expander
中添加属性和命令绑定(删除 ListView 中的ItemTapped
)
<xct:Expander
IsExpanded="{Binding Flag,Mode=TwoWay}"
Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:PageViewModel},Mode=FindAncestorBindingContext},Path=TapCommand}"
CommandParameter="{Binding .}">
,
我通过在扩展器的堆栈布局上使用命令在 ViewModel 中解决了这个问题:
在 Xaml 中 - 以两个扩展器为例:
xct:Expander.Header ...
xct:Expander.Header> ...
在视图模型中:
// 变量声明
私有扩展器_openExpander = new Expander();
公共命令 OnExpanderTappedCommand { get;放; }
// 在构造函数中
OnExpanderTappedCommand = new Command((o) => OnExpanderTappedCommandExecute(o));
//命令执行方法
private void OnExpanderTappedCommandExecute(object o)
{
Expander currentExpanderClicked = (Expander)o;
if (currentExpanderClicked.IsExpanded)
{
_openExpander.IsExpanded = false;
_openExpander = currentExpanderClicked;
_openExpander.IsExpanded = true;
}
}
也许对研究这个的人有用。我的灵感来自原始帖子的广泛逻辑。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。