C# 如何知道在ListView中修改了哪个Xamarin表单条目?
我在一个PCL项目中与Xamarin.Forms合作 我有一个页面/屏幕,其中有一个ListView控件。我已经为ViewCell创建了自定义数据模板 此ViewCell具有不同的控件:一些标签、一个按钮和一个条目C# 如何知道在ListView中修改了哪个Xamarin表单条目?,c#,listview,custom-controls,xamarin.forms,C#,Listview,Custom Controls,Xamarin.forms,我在一个PCL项目中与Xamarin.Forms合作 我有一个页面/屏幕,其中有一个ListView控件。我已经为ViewCell创建了自定义数据模板 此ViewCell具有不同的控件:一些标签、一个按钮和一个条目 <ListView x:Name="lvProducts" > <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout
<ListView x:Name="lvProducts" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#FFFFFF" Orientation="Vertical">
<Grid Padding="5">
...
<Button Grid.Row="0" Grid.Column="1" Text="X"
CommandParameter="{Binding MarkReference}"
Clicked="DeleteItemClicked" />
...
<StackLayout Grid.Row="2" Grid.ColumnSpan="2" Orientation="Horizontal" >
<Label Text="Ref.: " FontSize="24" FontAttributes="Bold" TextColor="#000000" />
<Label Text="{Binding Reference}" FontSize="24" TextColor="#000000" />
</StackLayout>
...
<Entry Grid.Row="3" Grid.Column="1" Text="{Binding NumElements}"
Keyboard="Numeric" Placeholder="" FontSize="24"
HorizontalTextAlignment="Center" Focused="OnItemFocus"
Unfocused="OnItemUnfocus" />
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
如何实现这两点?我建议您使用以下行为:
public class FocusBehavior : Behavior<Entry>
{
private Entry _entry;
public static readonly BindableProperty IsFocusedProperty =
BindableProperty.Create("IsFocused",
typeof(bool),
typeof(FocusBehavior),
default(bool),
propertyChanged: OnIsFocusedChanged);
public int IsFocused
{
get { return (int)GetValue(IsFocusedProperty); }
set { SetValue(IsFocusedProperty, value); }
}
protected override void OnAttachedTo(Entry bindable)
{
base.OnAttachedTo(bindable);
_entry = bindable;
}
private static void OnIsFocusedChanged(BindableObject bindable, object oldValue, object newValue)
{
var behavior = bindable as FocusBehavior;
var isFocused = (bool)newValue;
if (isFocused)
{
behavior._entry.Focus();
}
}
}
<ListView x:Name="TasksListView"
ItemsSource={Binding Tasks}
RowHeight="200">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell x:Name="ViewCell">
<Grid x:Name="RootGrid"
Padding="10,10,10,0"
BindingContext="{Binding}">
<Entry>
<Entry.Behaviors>
<helpers:FocusBehavior IsFocused="{Binding BindingContext.IsFocused, Source={x:Reference RootGrid}}"/>
</Entry.Behaviors>
</Entry>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
在ViewModel中,添加新项后,将其IsFocused
属性设置为true
对于行为,你可以使用
TextChanged
进行输入。对于我的第一个问题,我找到了一种解决方法。我不知道这是否是最好的解决办法
我已将ListView扩展到CustomListView,并添加了一个单元格字典:
private Dictionary<string, Cell> dicCells;
当单元格被移除时,UnhookContent将激发。我删除字典中存在的项
//When a new cell item has removed, we remove from the dictionary
protected override void UnhookContent(Cell content)
{
base.UnhookContent(content);
ViewCell vc = (ViewCell)content;
if (vc != null)
{
BasketProduct bp = (BasketProduct)vc.BindingContext;
if (bp != null)
{
this.dicCells.Remove(bp.MarkReference);
}
}
}
然后,我创建了一个函数,用于检索包含对象(在我的例子中是BasketProduct)的条目(在我的例子中是CustomEntry)
当我想将焦点放在某个条目上时,我调用此方法:
//Put the focus on the CustomEntry control that represents de BasketProduct that they have passed
public void SetSelected(BasketProduct bp, bool withDelay)
{
CustomEntry entry = null;
entry = GetEntry(bp);
if (entry != null)
{
if (withDelay)
{
FocusDelay(entry);
} else
{
entry.Focus();
}
}
}
如果我从ItemTapped方法调用SetSelected()方法,效果很好,但是如果我在then集合中添加一个项后调用SetSelected()方法,则该项不会获得焦点。在这种情况下,我做了一个诡计
private async void FocusDelay(CustomEntry entry)
{
await Task.Delay(500);
entry.Focus();
}
关于第二个问题,正如@markusian所建议的,我已经扩展了Entry(CustomEntry)控件,在未聚焦的事件中,我已经这样做了:
private void CustomEntry_Unfocused(object sender, FocusEventArgs e)
{
try
{
//If the user leaves the field empty, we set the last value
BasketProduct bp = (BasketProduct)BindingContext;
if (this.Text.Trim().Equals(string.Empty))
{
this.Text = bp.NumElements.ToString();
}
}
catch (FormatException ex) { }
}
关于第二点,如果需要访问数据对象,可以覆盖单元格中的
OnBindingContextChanged
,然后使用var object=(YourClass)BindingContext
获取对象。通过这种方式,您可以在需要时访问数据源中的对象。谢谢@markusian,我了解您的想法,我已经使用过它。我扩展了入口控制,并将其用于非焦点事件。很好。谢谢@EgorGromadskiy!你帮助我获得了灵感。我从来没有和行为学打过交道。我必须研究它。
//Retrieves a CustomEntry control that are into the collection and represents the BasketProduct that we have passed
public CustomEntry GetEntry(BasketProduct bp)
{
CustomEntry ce = null;
if (bp != null && this.dicCells.ContainsKey(bp.MarkReference))
{
ViewCell vc = (ViewCell)this.dicCells[bp.MarkReference];
if (vc != null)
{
ce = (CustomEntry)((Grid)((StackLayout)vc.View).Children[0]).Children[4];
}
}
return ce;
}
//Put the focus on the CustomEntry control that represents de BasketProduct that they have passed
public void SetSelected(BasketProduct bp, bool withDelay)
{
CustomEntry entry = null;
entry = GetEntry(bp);
if (entry != null)
{
if (withDelay)
{
FocusDelay(entry);
} else
{
entry.Focus();
}
}
}
private async void FocusDelay(CustomEntry entry)
{
await Task.Delay(500);
entry.Focus();
}
private void CustomEntry_Unfocused(object sender, FocusEventArgs e)
{
try
{
//If the user leaves the field empty, we set the last value
BasketProduct bp = (BasketProduct)BindingContext;
if (this.Text.Trim().Equals(string.Empty))
{
this.Text = bp.NumElements.ToString();
}
}
catch (FormatException ex) { }
}