2012-10-05 35 views
2

的問題是相同的,與MVVMCross不是編程,但我不知道是否有一個「跨平臺」的解決方案:當單擊ListView上的ImageButton時,MVVMCross是否可以更改選擇器?

在使用上MvxBindableListView一個的ImageButton(或一個ListView),我們必須把某些選項,以便使用此按鈕上的動作:

 <ImageButton 
      ... 
      android:focusable="false" 
      android:clickable="true" 
      ... 
      local:MvxBind="'Click':{'Path':'Command1'}}" 
      /> 

使用這些參數,按鈕對「Command1」作出反應。 但問題是ListView的「視覺選擇器」沒有改變。

讓我們舉一個例子:

當你在你的ListView 5行,第一個被選中。我觸摸第三行的ImageButton,「Command1」將響應(與ListView的第三項),但選擇器將停留在第一行。

因此,在Android中,我們必須把某種這樣的代碼:

_imagebutton.Click += (object sender, EventArgs eventsArgs) => 
    { 
     View v = ... 
     MvxBindableListView l = ... 
     int p = l.GetPositionForView(...); 
     l.PerformItemClick(..., p, p); 
    }; 

隨着這段代碼右邊的項目選擇和行爲是正確的(只要我不想用ItemClick發射一個真實的事件)。但這個解決方案是「Android方式」,並不是真正的跨平臺(我讓你想象一下可怕的代碼來初始化所有這些東西)

有人有更好的解決方案嗎?

雨果

回答

1

晴,這種感覺就像這僅僅是「UI眼睛糖果」 - 和「查看關注」域內所以瀑布 - 所以它不是mvvmcross東西通常試圖使跨平臺。

但是......我認爲有一種方法。

如果ViewModel中的命令處理程序也在ViewModel上設置CurrentSelectedPosition整數,則每個UI都可以將ViewModel中的SelectedItemPosition綁定到每個UI中的每個列表 - 這應該會導致UI本地更新選擇。

我認爲這工作...但在Android上就需要一些綁定:

public class MvxAdapterViewSelectedItemPositionTargetB-inging : MvxBaseAndroidTargetBinding 
{ 
    private readonly AdapterView _adapterView; 

    public MvxAdapterViewSelectedItemPositionTargetBinging(AdapterView adapterView) 
    { 
     _adapterView = adapterView; 
     _adapterView.ItemSelected += AdapterViewOnItemSelected; 
    } 

    public override void SetValue(object value) 
    { 
     _adapterView.SetSelection((int)value); 
    } 

    private void AdapterViewOnItemSelected(object sender, AdapterView.ItemSelectedEventArgs itemSelectedEventArgs) 
    { 
     FireValueChanged(itemSelectedEventArgs.Position); 
    } 

    public override MvxBindingMode DefaultMode 
    { 
     get 
     { 
      return MvxBindingMode.TwoWay; 
     } 
    } 

    public override Type TargetType 
    { 
     get 
     { 
      return typeof(Int32); 
     } 
    } 

    protected override void Dispose(bool isDisposing) 
    { 
     if (isDisposing) 
     { 
      if (_adapterView != null) 
      { 
       _adapterView.ItemSelected -= AdapterViewOnItemSelected; 
      } 
     } 
     base.Dispose(isDisposing); 
    } 
} 

使用註冊:

 registry.RegisterFactory(new MvxCustomBindingFactory<AdapterView>("SelectedItemPosition", adapterView => new MvxAdapterViewSelectedItemPositionTargetBinging(adapterView))); 

並綁定到UI中axml例如如:

<Mvx.MvxBindableListView 
    android:id="@android:id/list" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    local:MvxBind="{'ItemsSource':{'Path':'Emails'},'SelectedItemPosition':{'Path':'CurrentSelectedPosition'}}" 
    local:MvxItemTemplate="@layout/listitem_email" 
/> 

我使用一個電子郵件列表,其中視圖模型列表項目進行了檢驗這個想法:

public class SimpleEmail 
    { 
     public EmailViewModel Parent { get; set; } 
     public string From { get; set; }  
     public string Header { get; set; }  
     public string Message { get; set; }  
     public ICommand Command1 
     { 
      get 
      { 
       return new MvxRelayCommand(() => Parent.CurrentSelectedPosition = Parent.Emails.IndexOf(this)); 
      } 
     } 
    } 
  • 但顯然這只是一個演示...

注意:我在上面的代碼中使用了選定的位置而不是選定的對象 - 因爲我知道您使用的列表是ar非常長!


如果要考慮不同的方法來讓您的Android只有代碼,那麼我認爲你可以從Mvx.MvxBindableListView繼承(也可能是列表項太多),並使用這些類更新做選擇可能不那麼痛苦。

+0

嗨,斯圖亞特,再次感謝您的快速回答。看起來Android對_adapterView.SetSelection((int)值)沒有反應。這就是爲什麼我必須在正確的位置上對ListView執行PeformItemClick。不過,你的解決方案更漂亮,因爲它本身就是鏈接在ListView上的。我會嘗試從MvxBindableListView繼承,只要我有時間(截止日期快到了!) – hugoterelle

+0

AdapterView似乎在這裏響應SetSelection - 但也許這取決於你的「視覺選擇器」是什麼。我認爲state_selected和state_pressed是有區別的 - 但我不是這方面的專家! – Stuart

相關問題