2016-03-23 12 views
1

私はPCLプロジェクトのXamarin.Formsで作業しています。どのXamarinフォームエントリがListViewで変更されたかを知るには?

ListViewコントロールがあるページ/画面があります。 ViewCell用のカスタムDataTemplateを作成しました。

このViewCellは、いくつかのラベル、1つのボタン、1つのエントリを持っています。私は達成できないんだけど、このエントリ制御と二つのことを達成したい

<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> 

まず、私は新しい項目を追加するとき、私はこの新しいアイテムがフォーカスを彼のエントリを持つことを希望、入力を開始する準備が整いました。

第2に、ユーザーがエントリに値を書き込むために終了すると、後ろの値を変更したいと思います。 ListViewのどのエントリが変更されたのか知りたい。私はUnfocusedイベントを使用しようとしましたが、起動するメソッドのパラメータにはEntryオブジェクトを返す送信側パラメータのみがバインドされたモデルについての参照はありません。

public void OnItemUnfocus(object sender, EventArgs e) 
    { 
     Entry entry = (Entry)sender; 
     //Here I would like to know the model object that's binded 
     //with this Entry/CellView item 
    } 

どのようにこれらの2点を達成できますか?私はあなたが行動を使用することをお勧めしたいと思い

+1

をセル内で 'OnBindingContextChanged'をオーバーライドし、' var object =(YourClass)BindingContext'でオブジェクトを取得することができます。これにより、必要に応じてデータソース内のオブジェクトにアクセスできます。 – markusian

+1

@markusianありがとう、私はあなたの考えを持って、私はそれを使用しています。私はEntryコントロールを拡張し、Unfocusedイベントに使用しました。正常に動作します。 – stivex

答えて

-1

私の最初の質問のために、私はそれを解決する方法を見つけました。私はそれが最善の解決策かどうかわかりません。私はCustomListViewにリストビューを拡張した、及びIを添加した細胞の辞書

private Dictionary<string, Cell> dicCells; 

また、IはSetupContentとUnhookContentメソッドをオーバーライドしています。

SetupContentは、新しいセルが追加され、そのパラメータの1つが私に辞書に保存された新しいセルを与えるときに起動します。 (MarkReferenceは私の重要な値です)

//When a new cell item has added, we save it into a dictionary 
    protected override void SetupContent(Cell content, int index) 
    { 
     base.SetupContent(content, index); 

     ViewCell vc = (ViewCell)content;    

     if (vc != null) 
     { 
      BasketProduct bp = (BasketProduct)vc.BindingContext; 
      if (bp != null) 
      { 
       this.dicCells.Add(bp.MarkReference, content); 
      }     
     } 

    } 

セルが削除されたときに呼び出されます。私は辞書に存在する項目を削除します。

//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)のエントリを取得する関数を作成しました。

//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(); 
      }         
     }    
    } 

私は、正常に動作し、ItemTapped方法からするsetSelected()メソッドを呼び出した場合、私は呼び出す場合コレクション内にアイテムを追加した後にSetSelected()メソッドを呼び出すと、そのエントリはフォーカスを取得しません。この場合、私はトリックをしました。 2番目の質問について

private async void FocusDelay(CustomEntry entry) 
    {    
     await Task.Delay(500); 
     entry.Focus(); 
    } 

@markusianが示唆したように、私はエントリ(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) { } 
    } 
3

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> 

そして、私のモデル:

public class TaskModel : INotifyPropertyChanged 
{ 
    private bool _isFocused; 

    public bool IsFocused 
    { 
     get { return _isFocused; } 
     set 
     { 
      _isFocused = value; 
      RaisePropertyChanged(); 
     } 
    } 

とViewModelにに、新しい項目を追加した後、それはtrueIsFocusedプロパティの設定

同じことを入力のためにTextChangedに使用することができます。

+0

ありがとう@EgorGromadskiy!あなたは私にインスピレーションを与えるのを手伝ってくれました。私は行動で働いたことはありません。私はそれを勉強しなければならない。 – stivex

関連する問題