Closed ufbycd closed 3 years ago
你在微信群里吗,把完整的demo发个我看看吧
不在微信群,demo在这里:https://gitee.com/ufbycd/miniv2.git 基于awtk-mvvm-c-hello,并添加了awtk-widget-gesture-lock控件
好的,谢谢。明天我看看。
需要按下面的方式绑定:
<gesture_lock name="lock" h="80%" v-data:value="{password, Mode=OneWayToModel}" />
控件本身也有点问题,你可以等作者更新,或者先打上下面的补丁:
diff --git a/src/gesture_lock/gesture_lock.c b/src/gesture_lock/gesture_lock.c
index ba77b96..b15c189 100644
--- a/src/gesture_lock/gesture_lock.c
+++ b/src/gesture_lock/gesture_lock.c
@@ -30,7 +30,7 @@ static ret_t gesture_lock_get_prop(widget_t* widget, const char* name, value_t*
ret_t ret = RET_NOT_FOUND;
log_debug("%s(%s)\n", __func__, name);
- if (tk_str_eq(name, GESTURE_LOCK_PROP_PASSWORD)) {
+ if (tk_str_eq(name, GESTURE_LOCK_PROP_PASSWORD) || tk_str_eq(name, WIDGET_PROP_VALUE)) {
value_set_str(v, gesture_lock->password);
ret = RET_OK;
}else if (tk_str_eq(name, WIDGET_PROP_TYPE)) {
@@ -47,7 +47,7 @@ static ret_t gesture_lock_set_prop(widget_t* widget, const char* name, const val
ret_t ret = RET_NOT_FOUND;
log_debug("%s(%s)\n", __func__, name);
- if (tk_str_eq(name, GESTURE_LOCK_PROP_PASSWORD)) {
+ if (tk_str_eq(name, GESTURE_LOCK_PROP_PASSWORD) || tk_str_eq(name, WIDGET_PROP_VALUE)) {
const char *password = value_str(v);
return_value_if_fail(password != NULL, RET_BAD_PARAMS);
gesture_lock->password = tk_str_copy(gesture_lock->password, password);
@@ -258,7 +258,7 @@ static ret_t gesture_lock_on_pointer_up(widget_t* widget, pointer_event_t* evt)
value_change_event_init(&event, EVT_VALUE_CHANGED, widget);
value_set_str(&event.old_value, gesture_lock->password);
value_set_str(&event.new_value, gesture_lock->input_password.str);
- widget_dispatch(widget, (event_t*)&evt);
+ widget_dispatch(widget, (event_t*)&event);
gesture_lock->password = gesture_lock->input_password.str;
log_debug("gesture_lock: EVT_VALUE_CHANGED: %s\n", gesture_lock->password);
按上面修改后数据绑定成功了。
但在程序改进时又遇到一个问题:我想在EVT_VALUE_CHANGED
事件发生后就立刻执行 auth
于是控件UI改成这样:
<gesture_lock name="lock" h="80%" v-data:value="{password, Mode=OneWayToModel}" v-on:value_changed="{auth}" />
然而此时数据绑定就又没有成功了,似乎value_changed
的命令绑定会跟其数据绑定冲突,两者不能同时绑定。
怎么解决这个问题?
我找到一种解决办法:
数据绑定在Trigger=Changing
之上:
<gesture_lock name="lock" h="80%" v-data:value="{password, Mode=OneWayToModel, Trigger=Changing}" v-on:value_changed="{auth}" />
控件先发EVT_VALUE_CHANGING
事件,再发EVT_VALUE_CHANGED
事件:
value_change_event_init(&event, EVT_VALUE_CHANGING, widget);
gesture_lock->password = gesture_lock->input_password.str;
value_set_str(&event.old_value, gesture_lock->password);
value_set_str(&event.new_value, gesture_lock->password);
widget_dispatch(widget, (event_t*)&event);
event.e.type = EVT_VALUE_CHANGED;
widget_dispatch(widget, (event_t*)&event);
问题虽然解决了,但感觉绑定value_changed
有些坑,解决办法也有点拙劣。能否优化下?
看了下awtk-mvvm的代码后,找到更好的实现方式了:
将数据绑定到password
属性名之上:
<gesture_lock v-data:password="{password, Mode=OneWayToModel}" v-on:value_changed="{auth}" />
控制先发EVT_PROP_CHANGED
来更新model
里的属性,再发EVT_VALUE_CHANGED
事件来触发绑定的命令:
value_change_event_t vce;
prop_change_event_t pce;
value_t value;
gesture_lock->password = gesture_lock->input_password.str;
value_set_str(&value, gesture_lock->password);
prop_change_event_init(&pce, EVT_PROP_CHANGED, GESTURE_LOCK_PROP_PASSWORD, &value);
widget_dispatch(widget, (event_t*)&pce);
value_change_event_init(&vce, EVT_VALUE_CHANGED, widget);
value_set_str(&vce.old_value, gesture_lock->password);
value_set_str(&vce.new_value, gesture_lock->password);
widget_dispatch(widget, (event_t*)&vce);
自定义控件
gesture_lock
有个自定义属性password
,要跟modelgesture_login
的属性password
绑定时,发现gesture_lock
发出EVT_VALUE_CHANGED
事件后model的属性没有变化。widget:
model:
gesture_login.xml:
运行时的log输出:
自定义属性的绑定要怎么做?