Open ufbycd opened 3 weeks ago
两个列表相互关联,所以让单个view-model显示两列表。我按如下实现了view-model,初始化时两个表示的内容显示正确,但列表内容修改后,列表在显示上没有更新。什么问题?
<dialog x="c" y="m" w="50%" h="80%" v-model="assay_selector"> <dialog_title name="title" x="0" y="0" w="100%" h="40" tr_text="选择检测项目" /> <dialog_client x="0" y="40" w="100%" h="-100" children_layout="default(r=1,c=2,s=10)"> <list_view item_height="50"> <label x="0" y="0" w="100%" h="50" style="table_title" tr_text="检测项目" /> <scroll_view name="names" x="0" y="50" w="100%" h="-50"> <list_item v-for="{names}" children_layout="default(r=1,c=1)" v-on:click="{select_name, Args=fscript?index=index, IsContinue=true}"> <property name="v-data:style"> <![CDATA[ {(index == selected_name_index) ? "selected" : "default"} ]]> </property> <label v-data:text="{item}" /> </list_item> </scroll_view> <scroll_bar_m x="right" y="50" w="9" h="-50" value="0" /> </list_view> <list_view item_height="50"> <label x="0" y="0" w="100%" h="50" style="table_title" tr_text="批次" /> <scroll_view name="lots" x="0" y="50" w="100%" h="-50"> <list_item v-for="{lots}" children_layout="default(r=1,c=1)" v-on:click="{select_lot, Args=fscript?index=index, IsContinue=true}"> <property name="v-data:style"> <![CDATA[ {(index == selected_lot_index) ? "selected" : "default"} ]]> </property> <label v-data:text="{item}" /> </list_item> </scroll_view> <scroll_bar_m x="right" y="50" w="9" h="-50" value="0" /> </list_view> </dialog_client> <button name="ok" x="40" y="bottom:10" w="200" h="40" tr_text="确定" v-on:click="{confirm}" /> <button name="cancel" x="right:40" y="bottom:10" w="200" h="40" tr_text="取消" on:click="close()" /> </dialog>
#include "assay_selector_vm.h" #include "repository/assay_repository.h" #include "common/common.h" #include "pubsub.h" #include "mvvm/base/view_model_array.h" #include "mvvm/base/navigator.h" #include "mvvm/base/utils.h" typedef struct assay_selector_vm { view_model_array_t view_model_array; tk_object_t *names; tk_object_t *lots; int selected_name_index; int selected_lot_index; } assay_selector_vm_t; static assay_selector_vm_t* _cast(tk_object_t* obj); static ret_t _get_prop(tk_object_t* obj, const char* name, value_t* v) { assay_selector_vm_t* asvm = _cast(obj); return_value_if_fail(asvm != NULL, RET_BAD_PARAMS); ret_t ret = RET_NOT_FOUND; log_debug("%s: %s\n", __func__, name); if(view_model_array_default_get_prop(VIEW_MODEL(obj), name, v) == RET_OK) { ret = RET_OK; } else if (tk_str_eq(name, "names")) { value_set_object(v, asvm->names); ret = RET_OK; } else if(tk_str_eq(name, "lots")) { value_set_object(v, asvm->lots); ret = RET_OK; } else if(tk_str_eq(name, "selected_name_index")) { value_set_int(v, asvm->selected_name_index); ret = RET_OK; } else if(tk_str_eq(name, "selected_lot_index")) { value_set_int(v, asvm->selected_lot_index); ret = RET_OK; } // names.[<index>] else if(tk_str_start_with(name, "names.")) { ret = tk_object_get_prop(asvm->names, name + 6, v); } // lots.[<index>] else if(tk_str_start_with(name, "lots.")) { ret = tk_object_get_prop(asvm->lots, name + 5, v); } return ret; } static ret_t _set_prop(tk_object_t* obj, const char* name, const value_t* v) { return RET_NOT_IMPL; } static ret_t _remove_prop(tk_object_t* obj, const char* name) { return RET_NOT_IMPL; } static bool_t _can_exec(tk_object_t* obj, const char* name, const char* args) { assay_selector_vm_t* asvm = _cast(obj); return_value_if_fail(asvm != NULL, false); bool_t b = false; if(tk_str_eq(name, "select_name")) { b = true; } else if(tk_str_eq(name, "select_lot")) { b = true; } else if(tk_str_eq(name, "confirm")) { uint32_t names_len = tk_object_get_prop_uint32(asvm->names, TK_OBJECT_PROP_SIZE, 0); uint32_t lots_len = tk_object_get_prop_uint32(asvm->lots, TK_OBJECT_PROP_SIZE, 0); b = (asvm->selected_name_index >= 0) && (asvm->selected_lot_index >= 0) && (asvm->selected_name_index < names_len) && (asvm->selected_lot_index < lots_len); } return b; } static const char* _get_item_name(assay_selector_vm_t* asvm, int i) { char buf[16]; tk_snprintf(buf, sizeof(buf), "[%d]", i); const char* name = tk_object_get_prop_str(asvm->names, buf); return (name != NULL) ? name : ""; } static int _get_item_lot(assay_selector_vm_t* asvm, int i) { char buf[16]; tk_snprintf(buf, sizeof(buf), "[%d]", i); return tk_object_get_prop_int(asvm->names, buf, 0); } static ret_t _exec(tk_object_t* obj, const char* name, const char* args) { ret_t ret = RET_NOT_IMPL; assay_selector_vm_t* asvm = _cast(obj); return_value_if_fail(asvm != NULL, RET_BAD_PARAMS); if(tk_str_eq(name, "select_name")) { tk_object_t* a = object_default_create(); tk_command_arguments_to_object(args, a); int selected_index = tk_object_get_prop_int32(a, "index", asvm->selected_name_index); tk_object_unref(a); if(asvm->selected_name_index == selected_index) { ret = RET_OK; } else { asvm->selected_name_index = selected_index; char where[64]; const char* selected_name = _get_item_name(asvm, asvm->selected_name_index); tk_snprintf(where, sizeof(where), "name='%s'", selected_name); assay_repository_select_rows("lot", where, asvm->lots); asvm->selected_lot_index = -1; uint32_t lots_size = tk_object_get_prop_uint32(asvm->lots, TK_OBJECT_PROP_SIZE, 0); log_debug("lot list size: %u\n", lots_size); ret = RET_ITEMS_CHANGED; } } else if(tk_str_eq(name, "select_lot")) { tk_object_t* a = object_default_create(); tk_command_arguments_to_object(args, a); int selected_index = tk_object_get_prop_int32(a, "index", asvm->selected_lot_index); tk_object_unref(a); if(asvm->selected_lot_index == selected_index) { ret = RET_OK; } else { asvm->selected_lot_index = selected_index; ret = RET_OBJECT_CHANGED; } } else if(tk_str_eq(name, "confirm")) { assay_id_t aid; tk_strncpy(aid.name, _get_item_name(asvm, asvm->selected_name_index), sizeof(aid.name)); aid.lot = _get_item_lot(asvm, asvm->selected_lot_index); pubsub_publish(pubsub_topic_selected_assay, &aid, sizeof(aid)); ret = navigator_back(); } if (ret == RET_OBJECT_CHANGED) { // emitter_dispatch_simple_event(EMITTER(obj), EVT_PROPS_CHANGED); // emitter_dispatch_simple_event(EMITTER(obj), EVT_ITEMS_CHANGED); ret = RET_ITEMS_CHANGED; } return ret; } static ret_t _destroy(tk_object_t* obj) { assay_selector_vm_t* asvm = _cast(obj); return_value_if_fail(asvm != NULL, RET_BAD_PARAMS); tk_object_unref(asvm->names); tk_object_unref(asvm->lots); return RET_OK; } static const object_vtable_t _vtable = { .type = "assay_selector_vm_t", .desc = "assay selector VM", .size = sizeof(assay_selector_vm_t), .is_collection = false, .exec = _exec, .can_exec = _can_exec, .remove_prop = _remove_prop, .get_prop = _get_prop, .set_prop = _set_prop, .on_destroy = _destroy, }; static assay_selector_vm_t* _cast(tk_object_t* obj) { return_value_if_fail(obj != NULL && obj->vt == &_vtable, NULL); return (assay_selector_vm_t*)obj; } static const char* _preprocess_prop(view_model_t* view_model, const char* prop) { char index[TK_NUM_MAX_LEN + 1]; view_model_array_t* vm_array = VIEW_MODEL_ARRAY(view_model); return_value_if_fail(view_model != NULL && prop != NULL, NULL); if (tk_str_eq(prop, "item")) { tk_snprintf(index, TK_NUM_MAX_LEN, "[%d]", vm_array->cursor); str_set(&(vm_array->temp_prop), prop); str_replace(&(vm_array->temp_prop), "item", index); return vm_array->temp_prop.str; } else if (tk_str_start_with(prop, "item")) { tk_snprintf(index, TK_NUM_MAX_LEN, "[%d].", vm_array->cursor); str_set(&(vm_array->temp_prop), prop); str_replace(&(vm_array->temp_prop), "item_", index); str_replace(&(vm_array->temp_prop), "item.", index); return vm_array->temp_prop.str; } else if(tk_str_start_with(prop, "selected.")) { tk_snprintf(index, TK_NUM_MAX_LEN, "[%d].", vm_array->selected_index); str_set(&(vm_array->temp_prop), prop); str_replace(&(vm_array->temp_prop), "selected.", index); return vm_array->temp_prop.str; } else { return prop; } } view_model_t* assay_selector_vm_create(navigator_request_t* req) { tk_object_t* obj = tk_object_create(&_vtable); view_model_t* vm = view_model_array_init(VIEW_MODEL(obj)); assay_selector_vm_t* asvm = _cast(obj); return_value_if_fail(asvm != NULL, NULL); vm->preprocess_prop = _preprocess_prop; asvm->names = object_array_create(); asvm->lots = object_array_create(); asvm->selected_name_index = -1; asvm->selected_lot_index = -1; assay_repository_select_rows("name", NULL, asvm->names); assay_repository_select_rows("lot", "name='CK-MB'", asvm->lots); return vm; }
不行。你可以用两个ViewModel对应到同一个Model上。 view1 -> view_model1 -> model view2 -> view_model2 -> model
两个列表相互关联,所以让单个view-model显示两列表。我按如下实现了view-model,初始化时两个表示的内容显示正确,但列表内容修改后,列表在显示上没有更新。什么问题?