2012-12-19 15 views
5

Używam ZKOSS MVVM. Tak więc w widoku używam Listbox i jest on związany (@load) do obiektu modelu listy w ViewModel.zkoss MVVM zmienia siatkę sił modelu, aby ponownie załadować

Co rozumiem z dokumentacji, w przypadku zmiany modelu

1: Dodanie obiektu do listy modelu z widoku modelu o indeksie 0

I should see the latest object be appended at top of the Listbox. 

2: Usunięcie elementu z modelu

I should see that particular row from Listbox be removed. 

Uwaga: to interfejs podobny do sieci społecznościowej, np. Ściana Facebooka, gdy ktoś utworzy post, a nowy wpis zostanie dodany do listy postów. Jeśli wpis zostanie usunięty, tylko ten wpis został usunięty z listy

Cóż, tak się stało (nowy element zostanie usunięty/usunięty element zostanie usunięty), ale cały Listbox przeładowuje, a nie tylko ten konkretny wiersz, który został dodany lub usunięty .

Dlaczego tak jest? Dlaczego Listbox w pełni wczytuje zmiany modelu listy.

Każdy pomysł?

Oto fragmenty kodu (Use Case: Dodaj nowy post jest stosowane na tworzeniu nowego posta całością przeładowuje ListBox za każdym razem.):

View

<z:div style="height: 100%; padding: 0px; margin: 0px;" apply="org.zkoss.bind.BindComposer" 
    viewModel="@id('want_vm') @init('want.WantDesktopVM')"> 
<z:div zclass="content"> 
    <g:render template="../css/list/noEffectList"></g:render> 
    <z:div hflex="1" width="100%" visible="@load(want_vm.toggleInput)" style="margin-bottom: 5px; padding: 5px"> 
     <z:vbox> 
      <z:textbox id="postInput" multiline="true" value="" width="690px" height="50px"/> 
      <z:div hflex="1" width="100%" style="text-align: right; padding-right: 5px"> 
       <z:button label="Post" zclass="button rect theme" onClick="@command('post', text=postInput.value)"/> 
      </z:div> 
     </z:vbox>   
    </z:div> 
    <z:listbox model="@load(want_vm.posts)" emptyMessage="No new posts found." style="border:none;"> 
     <z:template name="model" var="iwant"> 
      <listitem style="margin-top: 10px"> 
       <listcell> 
        <hbox hflex="true"> 
         <div zclass="dpFrame small"> 
          <image height="50px" width="50px" content="@load(iwant.from) @converter('converter.UserActorDisplayPicConverter')" /> 
         </div> 
         <vbox hflex="true" zclass="post"> 
          <hbox hflex="true"> 
           <label value="@load(iwant.from) @converter('converter.ActorDisplayNameConverter')" zclass="displayName"/> 
          </hbox> 
          <hbox hflex="true"> 
           <label value="@load(iwant.textData)" zclass="post_data" multiline="true" maxlength="25"/> 
          </hbox> 
          <hbox> 
           <label value="@load(iwant.dateCreated) @converter('converter.SinceDateConverter')" zclass="since"/> 
          </hbox> 
         </vbox> 
        </hbox> 
       </listcell> 
      </listitem> 
     </z:template> 
    </z:listbox> 
</z:div> 

ViewModel

class WantDesktopVM { 
UserActorManagerService userActorManagerService 
ActivityManagerService activityManagerService 

UserActor me 
UserActor profile 

String error = null 
String view = 'iwant' 

@Wire 
Textbox postInput 

private List<Activity> posts = [] 

@Init 
public void init(@ContextParam(ContextType.COMPONENT) Component component, 
@ContextParam(ContextType.VIEW) Component view) { 
    profile = Executions.current.getAttribute("profile") 
    me = Executions.current.getAttribute("me") 
    loadPosts() 
} 

@AfterCompose 
public void afterCompose(@ContextParam(ContextType.VIEW) Component view) { 
    Selectors.wireComponents(view, this, false); 
} 

public boolean isMyProfile() { 
    return me.id == profile.id 
} 

public UserActor getMe() { 
    return this.me 
} 

public boolean isToggleInput() { 
    return this.view == 'iwant' && isMyProfile() 
} 

public List<Activity> getPosts() { 
    println "Getting posts ...${posts.size()}" 
    return this.posts 
} 

private List<Activity> loadPosts() { 
    if(view == 'iwant') { 
     posts = Activity.createCriteria().list() { 
      eq 'from', profile 
      eq 'type', ACTIVITY_TYPE.WANT 
      order("lastUpdated", "desc") 
     } 
    } else { 
     posts = ActorActivitySpace.createCriteria().list() { 
      projections {property("activity")} 
      eq 'actor', profile 
      activity { 
       ne 'from', profile 
       eq 'type', ACTIVITY_TYPE.WANT 
      } 
      order("lastUpdated", "desc") 
     } 
    } 
    return posts 
} 

@NotifyChange(['posts', 'toggleInput']) 
@Command 
public void render(@BindingParam('view') String view) { 
    println "Changing view ..." 
    this.view = view 
    loadPosts() 
} 

@NotifyChange('posts') 
@Command 
public void post(@BindingParam('text') String text) { 
    println "Posting text: $text" 
    postInput.setValue("") 
    if(text) { 
     Activity want = activityManagerService.want(me.id, text) 
     println"Want ID : $want.id" 
     posts.addAll(0, [want]) 
    } 
} 

}

+0

Proszę podać kod zawsze. Istnieją różne sposoby dodawania/usuwania komponentów, które powodują różne zachowania. –

+0

Zaktualizowałem wpis za pomocą fragmentów kodu. Proszę spojrzeć na: –

+0

Jakiego rodzaju lista 'Activity.createCriteria(). List()' zwraca? Gdzie podłączyć tę listę do siatki? –

Odpowiedz

5

Używasz @NotifyChange('posts'), aby powiedzieć ZK, że zmieniła się cała lista. Siatka nie próbuje przejrzeć listy, po prostu zastępuje obecną ListModel nową listą -> pełne przeładowanie.

Jeśli nie chcesz tego, będziesz musiał użyć metod z ListModel używanych przez sieć do aktualizacji interfejsu użytkownika. W ten sposób siatka będzie dokładnie wiedzieć, które wiersze się zmieniły i tylko je zaktualizować.

[EDIT] Aby osiągnąć to, co chcesz, wymienić List<Activity> posts z ListModelList<Activity> posts = new ListModelList<Activity>()

Kiedy działalność zmienić, trzeba aktualizacji ten list (tj zadzwonić add() lub addAll()) aktualizować poszczególne wiersze. Nie możesz już załadować wszystkiego z bazy danych, musisz scalić zmian w bazie danych z istniejącą listą.

+0

Jakieś konkretne dokumenty, do których możesz mnie polecić? To, co powiedziałeś, ma dla mnie sens, ale nie wiem, gdzie jest to wspomniane w ich dokumentach? –

+0

@AlamSher: Jak podłączyć model widoku do siatki? W powyższym kodzie ZUL nie ma elementu 'grid'. –

+0

proszę zobaczyć teraz. Zaktualizowałem pytanie, podając poprawny scenariusz i kod. Próbowałem zbyt wielu rzeczy, więc podczas wysyłania wiadomości zapomniałem, że zmieniłem kod. Odebrałem go od SVN :) –