我有一个带有自定义ViewCell的Xamarin.Forms ListView,其中包含带有条目和标签的StackLayout。我希望Entry能够在选择ViewCell的任何时候获得焦点。
ItemSelected
提供所选项目,但不提供ViewCell。我可以为ViewCell创建一个自定义类,但我不知道它何时可以知道它被选中。
如何将Entry集中在ListView项目选择上?
答案 0 :(得分:2)
将Entry移动到视图模型中,并将Entry绑定到ViewCell中的ContentView
。在ListView.ItemSelected
事件处理程序中,SelectedItem
现在包含条目,您可以在其中调用Focus
。
XAML如下所示:(在此示例中,条目包含数量。)
<ViewCell>
<StackLayout Orientation="Horizontal">
<ContentView Content="{Binding QuantityView}" />
<Label ... />
</StackLayout>
</ViewCell>
视图模型如下所示:
public class MyViewModel {
public string Quantity {get; set;}
public Entry QuantityView { get; } = new Entry {...};
public MyViewModel() {
QuantityView.SetBinding(Entry.TextProperty, nameof(Quantity));
}
}
ItemSelected
事件处理程序如下所示:
void FocusQuantity(object sender, SelectedItemChangedEventArgs e) {
if (e.SelectedItem == null) return;
((MyViewModel)e.SelectedItem).QuantityView.Focus();
}
答案 1 :(得分:0)
我这样做的方法是创建一个类 - 查看器 - 保存您想要的2个视图。然后将其用于ListView ItemSource,并专注于SelectedItem属性更改。
<强> Viewholder:强>
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));
}
}
MainPage(ListView Parent):
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);
}
}
}
<强> XAML:强>
<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事件,该事件是通过直接关注Entry而触发的,则可以将SelectedItem设置为包含Entry的ViewHolder。但它是非常丑陋的代码(当你看到我上面做过的事情时,它会说些什么!)参与寻找控制父母(和父母的父母)直到父母是列表视图(制作控制一个视单元),并将焦点设置到它。