在ListView项选择上聚焦ViewCell项
我有一个Xamarin.Forms ListView和一个自定义ViewCell,其中包含一个带有条目和标签的StackLayout。我希望该条目在选择ViewCell时获得焦点在ListView项选择上聚焦ViewCell项,listview,xamarin.forms,Listview,Xamarin.forms,我有一个Xamarin.Forms ListView和一个自定义ViewCell,其中包含一个带有条目和标签的StackLayout。我希望该条目在选择ViewCell时获得焦点 ItemSelected提供选定的项目,但不提供ViewCell。我可以为ViewCell创建自定义类,但我不知道它如何知道何时被选中 如何将条目集中在ListView项目选择上?我这样做的方式是创建一个类-Viewholder-它包含您想要的两个视图。然后将其用于ListView ItemSource,并关注Sele
ItemSelected
提供选定的项目,但不提供ViewCell。我可以为ViewCell创建自定义类,但我不知道它如何知道何时被选中
如何将条目集中在ListView项目选择上?我这样做的方式是创建一个类-Viewholder-它包含您想要的两个视图。然后将其用于ListView ItemSource,并关注SelectedItem属性的更改 视图持有者:
public class Viewholder
{
public Viewholder (){
}
public void OnFocus(){
Entry.Focus();
}
private Entry _entry ;
public Entry Entry{
get { return _entry;}
set{
if (value != null &&
_entry!= value){
_entry= value;
OnPropertyChanged();
}
}
private Label _label
public Label Label{
get { return _label;}
set{
if (value != null &&
_label!= value) {
_label= value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null){
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MainPage : ContentPage
{
public MainPage () {
SetUpControls();
}
private ObservableCollection<ViewHolder> _viewHolders;
public ObservableCollection<ViewHolder> ViewHolders
{
get { return _viewHolders;}
set{
if (value != null &&
_viewHolders!= value){
_viewHolders= value;
OnPropertyChanged();
}
}
private ViewHolder _selectedViewHolder;
public ViewHolder SelectedViewHolder{
get { return _selectedViewHolder;}
set{
if (value != null &&
_selectedViewHolder != value){
_selectedViewHolder= value;
OnPropertyChanged();
_selectedViewHolder.OnFocus();
}
}
private void SetUpControls(List<string> l){
foreach(var s in l){
ViewHolder v = new ViewHolder{
Label = new Label{
Text = s,
};
Entry = new Entry();
};
ViewHolders.Add(v);
}
if(l.Count > 0){
SelectedViewHolder = ViewHolders.ElementAt(0);
}
}
}
<ListView ItemsSource="{Binding ViewHolders, Mode=TwoWay}"
SelectedItem="{Binding SelectedViewHolder, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Content="{Binding Label, Mode="TwoWay"}/>
<ContentView Content="{Binding Entry, Mode="TwoWay"}/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
主页(ListView父级):
public class Viewholder
{
public Viewholder (){
}
public void OnFocus(){
Entry.Focus();
}
private Entry _entry ;
public Entry Entry{
get { return _entry;}
set{
if (value != null &&
_entry!= value){
_entry= value;
OnPropertyChanged();
}
}
private Label _label
public Label Label{
get { return _label;}
set{
if (value != null &&
_label!= value) {
_label= value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null){
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MainPage : ContentPage
{
public MainPage () {
SetUpControls();
}
private ObservableCollection<ViewHolder> _viewHolders;
public ObservableCollection<ViewHolder> ViewHolders
{
get { return _viewHolders;}
set{
if (value != null &&
_viewHolders!= value){
_viewHolders= value;
OnPropertyChanged();
}
}
private ViewHolder _selectedViewHolder;
public ViewHolder SelectedViewHolder{
get { return _selectedViewHolder;}
set{
if (value != null &&
_selectedViewHolder != value){
_selectedViewHolder= value;
OnPropertyChanged();
_selectedViewHolder.OnFocus();
}
}
private void SetUpControls(List<string> l){
foreach(var s in l){
ViewHolder v = new ViewHolder{
Label = new Label{
Text = s,
};
Entry = new Entry();
};
ViewHolders.Add(v);
}
if(l.Count > 0){
SelectedViewHolder = ViewHolders.ElementAt(0);
}
}
}
<ListView ItemsSource="{Binding ViewHolders, Mode=TwoWay}"
SelectedItem="{Binding SelectedViewHolder, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Content="{Binding Label, Mode="TwoWay"}/>
<ContentView Content="{Binding Entry, Mode="TwoWay"}/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public类主页:ContentPage
{
公共主页(){
设置控件();
}
私人可观察收藏(viewholder);;
公共可观测集合视图持有者
{
获取{return\u viewHolders;}
设置{
如果(值!=null&&
_视图持有者!=值){
_视图持有者=值;
OnPropertyChanged();
}
}
私有视图持有者_选择的视图持有者;
公共视图持有者已选择视图持有者{
获取{return\u selectedViewHolder;}
设置{
如果(值!=null&&
_selectedViewHolder!=值){
_selectedViewHolder=值;
OnPropertyChanged();
_selectedViewHolder.OnFocus();
}
}
专用控件(列表l){
foreach(l中的变量s){
ViewHolder v=新的ViewHolder{
标签=新标签{
Text=s,
};
条目=新条目();
};
视图持有者。添加(v);
}
如果(l.计数>0){
SelectedViewHolder=ViewHolders.ElementAt(0);
}
}
}
XAML:
public class Viewholder
{
public Viewholder (){
}
public void OnFocus(){
Entry.Focus();
}
private Entry _entry ;
public Entry Entry{
get { return _entry;}
set{
if (value != null &&
_entry!= value){
_entry= value;
OnPropertyChanged();
}
}
private Label _label
public Label Label{
get { return _label;}
set{
if (value != null &&
_label!= value) {
_label= value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null){
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MainPage : ContentPage
{
public MainPage () {
SetUpControls();
}
private ObservableCollection<ViewHolder> _viewHolders;
public ObservableCollection<ViewHolder> ViewHolders
{
get { return _viewHolders;}
set{
if (value != null &&
_viewHolders!= value){
_viewHolders= value;
OnPropertyChanged();
}
}
private ViewHolder _selectedViewHolder;
public ViewHolder SelectedViewHolder{
get { return _selectedViewHolder;}
set{
if (value != null &&
_selectedViewHolder != value){
_selectedViewHolder= value;
OnPropertyChanged();
_selectedViewHolder.OnFocus();
}
}
private void SetUpControls(List<string> l){
foreach(var s in l){
ViewHolder v = new ViewHolder{
Label = new Label{
Text = s,
};
Entry = new Entry();
};
ViewHolders.Add(v);
}
if(l.Count > 0){
SelectedViewHolder = ViewHolders.ElementAt(0);
}
}
}
<ListView ItemsSource="{Binding ViewHolders, Mode=TwoWay}"
SelectedItem="{Binding SelectedViewHolder, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Content="{Binding Label, Mode="TwoWay"}/>
<ContentView Content="{Binding Entry, Mode="TwoWay"}/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
这不是最好的选择,但对我来说很有效
此外,如果您添加了通过直接关注条目触发的OnSelection事件,您可以将SelectedItem设置为包含该条目的ViewHolder。但是这是一个非常难看的代码(当您看到我在上面所做的工作时,这说明了这一点!)涉及到查找控件父级(和父级)直到父对象成为listview(使控件成为viewcell),并将焦点设置为它。将条目移动到视图模型中,并将条目绑定到ViewCell中的
ContentView
。在ListView.ItemSelected
事件处理程序中,SelectedItem
现在包含可以调用focus
的条目
XAML如下所示:(在本例中,条目包含一个数量。)
视图模型如下所示:
公共类MyViewModel{
公共字符串数量{get;set;}
公共条目QuantityView{get;}=新条目{…};
公共MyViewModel(){
QuantityView.SetBinding(Entry.TextProperty,nameof(Quantity));
}
}
ItemSelected
事件处理程序如下所示:
void FocusQuantity(对象发送方,SelectedItemChangedEventArgs e){
if(e.SelectedItem==null)返回;
((MyViewModel)e.SelectedItem.QuantityView.Focus();
}
stacklayout上的点击手势可以忽略所选内容,重定向操作以聚焦条目吗?点击可能不会产生选择。例如,添加新项目时,会自动选中该项目,其条目应自动聚焦。您是否可以获取该项目的索引,然后抓取ViewCell手动基于索引?此解决方案违反了MVVM原则。为什么?通过向ViewModel添加条目
属性,它现在知道了太多关于View.Yup的细节。但在Xamarin.Forms允许之前,此解决方案属于MVVM纯度规范的whatugottado部分:-)