You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套ListView无记录时禁用PopupWindowShowAction的问题

问题背景

嵌套ListView场景下,存在一个依赖当前选中记录执行逻辑的PopupWindowShowAction操作:无对应选中记录时执行该操作会抛出错误,因此需要在无有效当前记录时将操作置为禁用状态。

以下是初始编写的简化版控制器代码:

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.ExpressApp.Editors;
using System;
using System.Linq;
using System.Windows.Forms;

namespace MyNamespace
{
    public partial class JobWorkflowController : ViewController
    {
        PopupWindowShowAction actWorkflow;
    

        public JobWorkflowController()
        {
            TargetObjectType = typeof(IWorkflow);
            actWorkflow = new PopupWindowShowAction(this, "Workflow", "Admin") 
            { 
                AcceptButtonCaption = string.Empty, 
                ActionMeaning = ActionMeaning.Accept, 
                CancelButtonCaption = null, 
                Caption = "Workflow", 
                ConfirmationMessage = null, 
                ImageName = "Workflow", 
                Shortcut = "F7", 
                ToolTip = null 
            };
            actWorkflow.CustomizePopupWindowParams += actWorkflow_CustomizePopupWindowParams_1;
            actWorkflow.Execute += actWorkflow_Execute_1;
            actWorkflow.Cancel += actWorkflow_Cancel;
        }

        private void actWorkflow_CustomizePopupWindowParams_1(object sender, CustomizePopupWindowParamsEventArgs e)
        {
            if (View.CurrentObject is not IWorkflow wf)
            {
                // 视图未初始化时执行到此处会触发错误
                return;
            }
             
            // 弹窗视图创建逻辑
        }

        private void actWorkflow_Execute_1(object sender, PopupWindowShowActionExecuteEventArgs e)
        {
           // 操作执行逻辑
        }

        private void actWorkflow_Cancel(object sender, EventArgs e)
        {
             // 操作取消逻辑
        }

        protected override void OnActivated()
        {
            base.OnActivated();
            View.CurrentObjectChanged += View_CurrentObjectChanged;
            View_CurrentObjectChanged(View, new EventArgs());
        }

        private void View_CurrentObjectChanged(object sender, EventArgs e)
        {
            actWorkflow.Enabled["HasCurrent"] = View.CurrentObject != null;
        }
        protected override void OnDeactivated()
        {
            View.CurrentObjectChanged -= View_CurrentObjectChanged;
            base.OnDeactivated();
        }
        
    }
}

目前已在OnActivated生命周期中订阅View.CurrentObjectChanged事件,在事件回调内通过设置actWorkflow.Enabled["HasCurrent"]属性值判断操作是否可用。经测试View_CurrentObjectChanged事件可正常触发,但操作并未按预期被禁用。

[更新]
尝试过Michael给出的建议方案,操作仍然无法正常禁用。

问题原因与修复方案

这个问题是嵌套ListView场景下的典型适配问题,核心原因有两点:

  1. 嵌套ListView(尤其是DetailView中通过ListPropertyEditor承载的嵌套列表)的选中状态变更,很多场景下只会触发SelectionChanged事件,不会触发CurrentObjectChanged事件,仅订阅后者会漏过大量状态变更场景。
  2. 自定义Action的启用规则没有结合框架自带的选择依赖逻辑,状态更新后没有主动触发Action刷新,嵌套Frame中的Action状态不会自动同步到UI层。

按以下步骤修改即可解决:

  • 给Action显式配置选择依赖类型,框架会自动接管大部分无选中、多选场景的禁用逻辑:
actWorkflow = new PopupWindowShowAction(this, "Workflow", "Admin") 
{ 
    // 保留原有初始化属性
    SelectionDependencyType = SelectionDependencyType.RequireSingleObject
};
  • 补充事件订阅覆盖所有选中变更场景,处理视图延迟加载的初始状态问题,更新状态后主动刷新Action同步UI:
protected override void OnActivated()
{
    base.OnActivated();
    // 同时订阅两个事件,覆盖普通视图、嵌套列表的所有选中变更场景
    View.CurrentObjectChanged += View_SelectedStateChanged;
    if(View is ListView lv)
    {
        lv.SelectionChanged += View_SelectedStateChanged;
    }
    // 视图未加载完成时,等加载完毕再初始化状态,避免初始状态显示错误
    if(View.IsLoaded)
    {
        View_SelectedStateChanged(View, EventArgs.Empty);
    }
    else
    {
        EventHandler onLoad = null;
        onLoad = (s,e) => 
        {
            View.Load -= onLoad;
            View_SelectedStateChanged(View, EventArgs.Empty);
        };
        View.Load += onLoad;
    }
}

// 统一处理选中状态变更后的Action可用性更新
private void View_SelectedStateChanged(object sender, EventArgs e)
{
    bool hasValidSelectedRecord = View.CurrentObject is IWorkflow;
    // ListView场景下通过SelectedObjects判断比CurrentObject更准确
    if(View is ListView listView)
    {
        hasValidSelectedRecord = listView.SelectedObjects.Count == 1 && listView.SelectedObjects[0] is IWorkflow;
    }
    actWorkflow.Enabled["HasCurrent"] = hasValidSelectedRecord;
    // 主动刷新Action状态,解决嵌套Frame下UI不同步问题
    actWorkflow.Refresh();
}

protected override void OnDeactivated()
{
    // 注销所有事件避免内存泄漏
    View.CurrentObjectChanged -= View_SelectedStateChanged;
    if(View is ListView lv)
    {
        lv.SelectionChanged -= View_SelectedStateChanged;
    }
    base.OnDeactivated();
}
  • 在弹窗参数自定义事件开头增加兜底校验,极端场景下状态同步延迟时也不会抛出底层错误:
private void actWorkflow_CustomizePopupWindowParams_1(object sender, CustomizePopupWindowParamsEventArgs e)
{
    if (View.CurrentObject is not IWorkflow wf)
    {
        throw new UserFriendlyException("请先选中一条工作流记录后再执行操作");
    }
    // 保留原有弹窗视图创建逻辑
}

内容的提问来源于stack exchange,提问作者Kirsten

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:01:18