Power Apps中多次调用Patch仅首次生效问题求助
问题场景
我有一个表单和按钮,希望将输入字段的数据提交至Table1表格。逻辑为:两个AppId字段分别对应两组属性字段,需创建/更新表格中的两行数据。代码如下:
Set(var_DataSet_Name, TXTInput_Dataset_Name.Value); Set(var_DataSet_Name_Lock, true); If( IsBlank(LookUp('Table1', 'AppId' = TextInput1_1.Value)), Notify("no records found", NotificationType.Error), Patch('Table1', LookUp('Table1', 'AppId' = TextInput1_1.Value), { 'attribute1': TextInput2_1.Value, 'attribute2': TextInput3_1.Value } ) ); If( IsBlank(LookUp('Table1', 'AppId' = TextInput1_2.Value)), Notify("no records found", NotificationType.Error), Patch('Table1', LookUp('Table1', 'AppId' = TextInput1_2.Value), { 'attribute1': TextInput2_2.Value, 'attribute2': TextInput3_2.Value } ) ); Refresh('Table1');
问题在于仅第一个Patch生效,仅AppId为TextInput1_1.Value的行被更新。调试发现:
- 调换两个Patch的顺序后,对应的另一行生效;
- 若将属性值替换为固定字符串(如
{ 'attribute1': "aaa", 'attribute2': "bbb" }),则两个Patch均正常工作。
核心原因
这是Power Apps单一事件执行流程中的控件值上下文干扰问题,主要有两种触发场景:
输入控件绑定了提前设置的变量
代码开头执行的Set(var_DataSet_Name, TXTInput_Dataset_Name.Value);,如果TextInput1_2、TextInput2_2或TextInput3_2的Default属性绑定了var_DataSet_Name,这行赋值会直接覆盖这些输入框的用户输入值。第一个Patch执行时,控件初始值还在缓存中能正常读取,但第二个Patch执行时,控件已完成重新渲染,Value变成了变量的新值,导致Lookup找不到目标记录,或Patch的属性值不符合预期,看起来像是未生效。多次Patch触发局部渲染导致缓存失效
Power Apps在事件触发时会缓存控件初始值,但第一个Patch执行后,Notify弹窗或数据源的微小变更可能触发页面局部渲染。后续代码读取控件值时,会读取到渲染后的状态(比如输入框依赖Table1的属性被重置)。而使用固定字符串时无需读取控件值,不受渲染影响,因此两个Patch都能正常执行。
解决办法
方法1:提前缓存所有输入值
在事件开头把所有需要用到的输入值存入变量,后续Patch直接使用变量,避免读取渲染后的控件值:
// 先缓存所有输入值 Set(var_AppId1, TextInput1_1.Value); Set(var_Attr1_1, TextInput2_1.Value); Set(var_Attr2_1, TextInput3_1.Value); Set(var_AppId2, TextInput1_2.Value); Set(var_Attr1_2, TextInput2_2.Value); Set(var_Attr2_2, TextInput3_2.Value); Set(var_DataSet_Name, TXTInput_Dataset_Name.Value); Set(var_DataSet_Name_Lock, true); // 用变量执行Patch If( IsBlank(LookUp('Table1', 'AppId' = var_AppId1)), Notify("no records found", NotificationType.Error), Patch('Table1', LookUp('Table1', 'AppId' = var_AppId1), { 'attribute1': var_Attr1_1, 'attribute2': var_Attr2_1 } ) ); If( IsBlank(LookUp('Table1', 'AppId' = var_AppId2)), Notify("no records found", NotificationType.Error), Patch('Table1', LookUp('Table1', 'AppId' = var_AppId2), { 'attribute1': var_Attr1_2, 'attribute2': var_Attr2_2 } ) ); Refresh('Table1');
方法2:调整变量设置时机
把变量赋值操作移到两个Patch执行完成后,避免提前覆盖输入控件的绑定值:
// 先执行Patch操作 If( IsBlank(LookUp('Table1', 'AppId' = TextInput1_1.Value)), Notify("no records found", NotificationType.Error), Patch('Table1', LookUp('Table1', 'AppId' = TextInput1_1.Value), { 'attribute1': TextInput2_1.Value, 'attribute2': TextInput3_1.Value } ) ); If( IsBlank(LookUp('Table1', 'AppId' = TextInput1_2.Value)), Notify("no records found", NotificationType.Error), Patch('Table1', LookUp('Table1', 'AppId' = TextInput1_2.Value), { 'attribute1': TextInput2_2.Value, 'attribute2': TextInput3_2.Value } ) ); // 再设置变量 Set(var_DataSet_Name, TXTInput_Dataset_Name.Value); Set(var_DataSet_Name_Lock, true); Refresh('Table1');
方法3:合并批量Patch操作
使用Patch的批量更新语法,一次提交两行数据,减少事件内的多次数据源操作:
Set(var_DataSet_Name, TXTInput_Dataset_Name.Value); Set(var_DataSet_Name_Lock, true); Patch( 'Table1', // 第一行记录:存在则更新,不存在则不创建(如需创建可去掉If判断) If(IsBlank(LookUp('Table1', 'AppId' = TextInput1_1.Value)), {}, LookUp('Table1', 'AppId' = TextInput1_1.Value)), { 'AppId': TextInput1_1.Value, 'attribute1': TextInput2_1.Value, 'attribute2': TextInput3_1.Value }, // 第二行记录 If(IsBlank(LookUp('Table1', 'AppId' = TextInput1_2.Value)), {}, LookUp('Table1', 'AppId' = TextInput1_2.Value)), { 'AppId': TextInput1_2.Value, 'attribute1': TextInput2_2.Value, 'attribute2': TextInput3_2.Value } ); // 补充找不到记录的提示 If(IsBlank(LookUp('Table1', 'AppId' = TextInput1_1.Value)), Notify("no records found for AppId1", NotificationType.Error)); If(IsBlank(LookUp('Table1', 'AppId' = TextInput1_2.Value)), Notify("no records found for AppId2", NotificationType.Error)); Refresh('Table1');
内容的提问来源于stack exchange,提问作者user26167691

