优化运动物体和碰撞目标的存储逻辑,更新数据库结构

This commit is contained in:
tian 2026-01-27 23:18:27 +08:00
parent 1e277a4bc3
commit c1e20bf4ee
6 changed files with 327 additions and 102 deletions

View File

@ -252,25 +252,14 @@ namespace NavisworksTransport.Core
{
throw new InvalidOperationException($"路径不存在 (Id: {item.PathRouteId})");
}
// 获取运动物体
ModelItem animatedObject = null;
bool isVirtualVehicle = item.IsVirtualVehicle;
if (!string.IsNullOrEmpty(item.VehicleObjectId))
{
animatedObject = FindModelItemById(item.VehicleObjectId);
isVirtualVehicle = false;
if (animatedObject == null)
{
throw new InvalidOperationException("未找到指定的运动物体");
}
LogManager.Info($"[批处理] 使用真实物体: {animatedObject.DisplayName}");
}
else if (isVirtualVehicle)
if (isVirtualVehicle)
{
// 🔥 使用现有的虚拟车辆,不创建和清理
// 使用现有的虚拟车辆,不创建和清理
// ShowVirtualVehicle 会显示虚拟车辆并更新尺寸(如果已存在)
VirtualVehicleManager.Instance.ShowVirtualVehicle(
item.VirtualVehicleLength,
@ -287,27 +276,108 @@ namespace NavisworksTransport.Core
LogManager.Info($"[批处理] 使用虚拟车辆: {animatedObject.DisplayName}");
}
// 初始化碰撞检测缓存
LogManager.Info("[批处理] 初始化碰撞检测缓存...");
ClashDetectiveIntegration.InitializeCollisionDetectionCache(animatedObject);
// 在主线程执行Navisworks API调用
var result = await UIStateManager.Instance.ExecuteUIUpdateAsync(() =>
else
{
// 预计算动画帧和碰撞
var config = new CollisionDetectionConfig
{
FrameRate = item.FrameRate,
DurationSeconds = item.DurationSeconds,
DetectionToleranceMeters = item.DetectionToleranceMeters,
VirtualVehicleLength = item.VirtualVehicleLength,
VirtualVehicleWidth = item.VirtualVehicleWidth,
VirtualVehicleHeight = item.VirtualVehicleHeight,
CollisionDetectionEnabled = true,
ReportGenerationEnabled = true
};
// 从 ModelItemReferences 表查询运动物体
var vehicleReferences = await _database.GetModelItemReferencesAsync(
item.Id,
"BatchQueueItem",
"Vehicle"
);
if (vehicleReferences.Count > 0)
{
var vehicleRef = vehicleReferences[0];
try
{
var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
{
ModelIndex = vehicleRef.Item1,
PathId = vehicleRef.Item2
};
animatedObject = Application.ActiveDocument.Models.ResolvePathId(pathIdObj);
if (animatedObject == null)
{
throw new InvalidOperationException("未找到指定的运动物体");
}
LogManager.Info($"[批处理] 使用真实物体: {animatedObject.DisplayName}");
}
catch (Exception ex)
{
LogManager.Error($"[批处理] 从 PathId 恢复运动物体失败: ModelIndex={vehicleRef.Item1}, PathId={vehicleRef.Item2}, 错误: {ex.Message}");
throw new InvalidOperationException("恢复运动物体失败", ex);
}
}
else
{
throw new InvalidOperationException("未找到运动物体的 ModelItem 引用");
}
}
// 初始化碰撞检测缓存
LogManager.Info("[批处理] 初始化碰撞检测缓存...");
ClashDetectiveIntegration.InitializeCollisionDetectionCache(animatedObject);
// 从 ModelItemReferences 表查询手工指定的检测物体(在主线程外完成查询)
List<ModelItem> manualDetectionTargets = null;
if (!item.DetectAllObjects)
{
var targetReferences = await _database.GetModelItemReferencesAsync(
item.Id,
"BatchQueueItem",
"CollisionTarget"
);
if (targetReferences.Count > 0)
{
manualDetectionTargets = new List<ModelItem>();
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
foreach (var targetRef in targetReferences)
{
try
{
var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
{
ModelIndex = targetRef.Item1,
PathId = targetRef.Item2
};
var modelItem = doc.Models.ResolvePathId(pathIdObj);
if (modelItem != null)
{
manualDetectionTargets.Add(modelItem);
}
else
{
LogManager.Warning($"[批处理] 无法通过 PathId 找到 ModelItem: ModelIndex={targetRef.Item1}, PathId={targetRef.Item2}");
}
}
catch (Exception ex)
{
LogManager.Warning($"[批处理] 恢复手工指定对象失败: {targetRef.Item3}, 错误: {ex.Message}");
}
}
LogManager.Info($"[批处理] 加载手工指定检测物体,成功: {manualDetectionTargets.Count}/{targetReferences.Count}");
}
}
// 在主线程执行Navisworks API调用
var result = await UIStateManager.Instance.ExecuteUIUpdateAsync(() =>
{
// 预计算动画帧和碰撞
var config = new CollisionDetectionConfig
{
FrameRate = item.FrameRate,
DurationSeconds = item.DurationSeconds,
DetectionToleranceMeters = item.DetectionToleranceMeters,
VirtualVehicleLength = item.VirtualVehicleLength,
VirtualVehicleWidth = item.VirtualVehicleWidth,
VirtualVehicleHeight = item.VirtualVehicleHeight,
CollisionDetectionEnabled = true,
ReportGenerationEnabled = true
};
var frames = _processor.PrecomputeFrames(
pathRoute,
animatedObject,
@ -318,7 +388,7 @@ namespace NavisworksTransport.Core
config.FrameRate,
config.DurationSeconds,
config.DetectionToleranceMeters,
null,
manualDetectionTargets,
item.ObjectRotationCorrection
);
@ -455,28 +525,7 @@ namespace NavisworksTransport.Core
await _database.DeleteBatchQueueItemAsync(itemId);
}
/// <summary>
/// 查找模型项
/// </summary>
private ModelItem FindModelItemById(string id)
{
try
{
var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
if (doc == null) return null;
var model = doc.Models.RootItemDescendants.FirstOrDefault(
item => item.ToString() == id
);
return model;
}
catch (Exception ex)
{
LogManager.Error($"查找模型项失败 (Id: {id}): {ex.Message}");
return null;
}
}
}
/// <summary>

View File

@ -16,32 +16,34 @@ namespace NavisworksTransport.Core.Models
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public string ErrorMessage { get; set; }
// 动画配置
public int FrameRate { get; set; }
public double DurationSeconds { get; set; }
// 碰撞检测配置
public double DetectionToleranceMeters { get; set; }
// 运动物体配置
public bool IsVirtualVehicle { get; set; }
public double VirtualVehicleLength { get; set; }
public double VirtualVehicleWidth { get; set; }
public double VirtualVehicleHeight { get; set; }
public string VehicleObjectId { get; set; }
public string VehicleObjectName { get; set; }
// 被检测项
public List<string> DetectionItems { get; set; } = new List<string>();
// 碰撞检测配置
public bool DetectAllObjects { get; set; } = true;
// 角度修正配置
public double ObjectRotationCorrection { get; set; }
// 结果
public string ClashDetectiveTestName { get; set; }
public int? CollisionCount { get; set; }
// 注意:运动物体和碰撞检测目标都存储在 ModelItemReferences 表中
// 使用 BatchQueueItem.Id 作为 ReferenceId 进行查询
// Role = "Vehicle" 表示运动物体
// Role = "CollisionTarget" 表示碰撞检测目标
}
/// <summary>

View File

@ -231,9 +231,9 @@ namespace NavisworksTransport
VirtualVehicleLength REAL,
VirtualVehicleWidth REAL,
VirtualVehicleHeight REAL,
VehicleObjectId TEXT,
VehicleModelIndex INTEGER,
VehiclePathId TEXT,
VehicleObjectName TEXT,
DetectionItems TEXT,
DetectAllObjects INTEGER NOT NULL DEFAULT 1,
ClashDetectiveTestName TEXT,
CollisionCount INTEGER,
@ -245,6 +245,23 @@ namespace NavisworksTransport
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_batch_queue_status ON BatchQueueItems(Status)");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_batch_queue_created ON BatchQueueItems(CreatedTime)");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_batch_queue_path ON BatchQueueItems(PathRouteId)");
// 通用 ModelItem 引用表(用于存储运动物体、碰撞物体等)
ExecuteNonQuery(@"
CREATE TABLE IF NOT EXISTS ModelItemReferences (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
ReferenceId INTEGER NOT NULL,
ReferenceType TEXT NOT NULL,
ModelIndex INTEGER NOT NULL,
PathId TEXT NOT NULL,
DisplayName TEXT,
ObjectName TEXT,
Role TEXT
)
");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_model_ref_reference ON ModelItemReferences(ReferenceId)");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_model_ref_type ON ModelItemReferences(ReferenceType)");
ExecuteNonQuery("CREATE INDEX IF NOT EXISTS idx_model_ref_path ON ModelItemReferences(PathId)");
}
/// <summary>
@ -1358,18 +1375,18 @@ namespace NavisworksTransport
PathRouteId, PathRouteName, Status, CreatedTime, StartTime, EndTime, ErrorMessage,
FrameRate, DurationSeconds, DetectionToleranceMeters,
IsVirtualVehicle, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight,
VehicleObjectId, VehicleObjectName, DetectionItems, DetectAllObjects,
DetectAllObjects,
ClashDetectiveTestName, CollisionCount, ObjectRotationCorrection
)
VALUES (
@PathRouteId, @PathRouteName, @Status, @CreatedTime, @StartTime, @EndTime, @ErrorMessage,
@FrameRate, @DurationSeconds, @DetectionToleranceMeters,
@IsVirtualVehicle, @VirtualVehicleLength, @VirtualVehicleWidth, @VirtualVehicleHeight,
@VehicleObjectId, @VehicleObjectName, @DetectionItems, @DetectAllObjects,
@DetectAllObjects,
@ClashDetectiveTestName, @CollisionCount, @ObjectRotationCorrection
);
SELECT last_insert_rowid();";
cmd.Parameters.AddWithValue("@PathRouteId", item.PathRouteId);
cmd.Parameters.AddWithValue("@PathRouteName", item.PathRouteName ?? "");
cmd.Parameters.AddWithValue("@Status", item.Status.ToString());
@ -1384,15 +1401,19 @@ namespace NavisworksTransport
cmd.Parameters.AddWithValue("@VirtualVehicleLength", item.VirtualVehicleLength);
cmd.Parameters.AddWithValue("@VirtualVehicleWidth", item.VirtualVehicleWidth);
cmd.Parameters.AddWithValue("@VirtualVehicleHeight", item.VirtualVehicleHeight);
cmd.Parameters.AddWithValue("@VehicleObjectId", item.VehicleObjectId ?? "");
cmd.Parameters.AddWithValue("@VehicleObjectName", item.VehicleObjectName ?? "");
cmd.Parameters.AddWithValue("@DetectionItems", item.DetectionItems != null ? string.Join(",", item.DetectionItems) : "");
cmd.Parameters.AddWithValue("@DetectAllObjects", item.DetectAllObjects ? 1 : 0);
cmd.Parameters.AddWithValue("@ClashDetectiveTestName", item.ClashDetectiveTestName ?? "");
cmd.Parameters.AddWithValue("@CollisionCount", item.CollisionCount ?? (object)DBNull.Value);
cmd.Parameters.AddWithValue("@ObjectRotationCorrection", item.ObjectRotationCorrection);
return Convert.ToInt32(cmd.ExecuteScalar());
var queueItemId = Convert.ToInt32(cmd.ExecuteScalar());
// 注意:运动物体和碰撞检测目标都存储在 ModelItemReferences 表中
// 这些数据在调用 CreateBatchQueueItemAsync 之前插入
// Role = "Vehicle" 表示运动物体
// Role = "CollisionTarget" 表示碰撞检测目标
return queueItemId;
}
});
}
@ -1411,7 +1432,7 @@ namespace NavisworksTransport
SELECT Id, PathRouteId, PathRouteName, Status, CreatedTime, StartTime, EndTime, ErrorMessage,
FrameRate, DurationSeconds, DetectionToleranceMeters,
IsVirtualVehicle, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight,
VehicleObjectId, VehicleObjectName, DetectionItems, DetectAllObjects,
DetectAllObjects,
ClashDetectiveTestName, CollisionCount, ObjectRotationCorrection
FROM BatchQueueItems";
var conditions = new List<string>();
@ -1465,9 +1486,6 @@ namespace NavisworksTransport
VirtualVehicleLength = Convert.ToDouble(reader["VirtualVehicleLength"]),
VirtualVehicleWidth = Convert.ToDouble(reader["VirtualVehicleWidth"]),
VirtualVehicleHeight = Convert.ToDouble(reader["VirtualVehicleHeight"]),
VehicleObjectId = reader["VehicleObjectId"].ToString(),
VehicleObjectName = reader["VehicleObjectName"].ToString(),
DetectionItems = reader["DetectionItems"].ToString() != "" ? reader["DetectionItems"].ToString().Split(',').ToList() : new List<string>(),
DetectAllObjects = Convert.ToBoolean(reader["DetectAllObjects"]),
ClashDetectiveTestName = reader["ClashDetectiveTestName"].ToString(),
CollisionCount = !Convert.IsDBNull(reader["CollisionCount"]) ? (int?)Convert.ToInt32(reader["CollisionCount"]) : null,
@ -1493,18 +1511,18 @@ namespace NavisworksTransport
SELECT Id, PathRouteId, PathRouteName, Status, CreatedTime, StartTime, EndTime, ErrorMessage,
FrameRate, DurationSeconds, DetectionToleranceMeters,
IsVirtualVehicle, VirtualVehicleLength, VirtualVehicleWidth, VirtualVehicleHeight,
VehicleObjectId, VehicleObjectName, DetectionItems, DetectAllObjects,
DetectAllObjects,
ClashDetectiveTestName, CollisionCount, ObjectRotationCorrection
FROM BatchQueueItems
WHERE Id = @Id";
cmd.Parameters.AddWithValue("@Id", itemId);
using (var reader = cmd.ExecuteReader())
{
if (reader.Read())
{
return new BatchQueueItem
var item = new BatchQueueItem
{
Id = Convert.ToInt32(reader["Id"]),
PathRouteId = reader["PathRouteId"].ToString(),
@ -1521,14 +1539,13 @@ namespace NavisworksTransport
VirtualVehicleLength = Convert.ToDouble(reader["VirtualVehicleLength"]),
VirtualVehicleWidth = Convert.ToDouble(reader["VirtualVehicleWidth"]),
VirtualVehicleHeight = Convert.ToDouble(reader["VirtualVehicleHeight"]),
VehicleObjectId = reader["VehicleObjectId"].ToString(),
VehicleObjectName = reader["VehicleObjectName"].ToString(),
DetectionItems = reader["DetectionItems"].ToString() != "" ? reader["DetectionItems"].ToString().Split(',').ToList() : new List<string>(),
DetectAllObjects = Convert.ToBoolean(reader["DetectAllObjects"]),
ClashDetectiveTestName = reader["ClashDetectiveTestName"].ToString(),
CollisionCount = !Convert.IsDBNull(reader["CollisionCount"]) ? (int?)Convert.ToInt32(reader["CollisionCount"]) : null,
ObjectRotationCorrection = Convert.ToDouble(reader["ObjectRotationCorrection"])
};
return item;
}
}
}
@ -1580,6 +1597,98 @@ namespace NavisworksTransport
});
}
/// <summary>
/// 添加 ModelItem 引用到 ModelItemReferences 表
/// </summary>
public async Task<int> AddModelItemReferenceAsync(int referenceId, string referenceType, int modelIndex, string pathId, string displayName, string objectName, string role)
{
return await Task.Run(() =>
{
using (var cmd = new SQLiteCommand(_connection))
{
cmd.CommandText = @"
INSERT INTO ModelItemReferences (ReferenceId, ReferenceType, ModelIndex, PathId, DisplayName, ObjectName, Role)
VALUES (@ReferenceId, @ReferenceType, @ModelIndex, @PathId, @DisplayName, @ObjectName, @Role);
SELECT last_insert_rowid();";
cmd.Parameters.AddWithValue("@ReferenceId", referenceId);
cmd.Parameters.AddWithValue("@ReferenceType", referenceType);
cmd.Parameters.AddWithValue("@ModelIndex", modelIndex);
cmd.Parameters.AddWithValue("@PathId", pathId);
cmd.Parameters.AddWithValue("@DisplayName", displayName ?? "");
cmd.Parameters.AddWithValue("@ObjectName", objectName ?? "");
cmd.Parameters.AddWithValue("@Role", role);
return Convert.ToInt32(cmd.ExecuteScalar());
}
});
}
/// <summary>
/// 获取指定 ReferenceId 和 Role 的所有 ModelItem 引用
/// </summary>
public async Task<List<(int ModelIndex, string PathId, string DisplayName, string ObjectName)>> GetModelItemReferencesAsync(int referenceId, string referenceType, string role = null)
{
return await Task.Run(() =>
{
var items = new List<(int, string, string, string)>();
using (var cmd = new SQLiteCommand(_connection))
{
var sql = @"
SELECT ModelIndex, PathId, DisplayName, ObjectName
FROM ModelItemReferences
WHERE ReferenceId = @ReferenceId AND ReferenceType = @ReferenceType";
if (!string.IsNullOrEmpty(role))
{
sql += " AND Role = @Role";
cmd.Parameters.AddWithValue("@Role", role);
}
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("@ReferenceId", referenceId);
cmd.Parameters.AddWithValue("@ReferenceType", referenceType);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
items.Add((
Convert.ToInt32(reader["ModelIndex"]),
reader["PathId"].ToString(),
reader["DisplayName"].ToString(),
reader["ObjectName"].ToString()
));
}
}
}
return items;
});
}
/// <summary>
/// 删除指定 ReferenceId 的所有 ModelItem 引用
/// </summary>
public async Task DeleteModelItemReferencesAsync(int referenceId, string referenceType = null)
{
await Task.Run(() =>
{
using (var cmd = new SQLiteCommand(_connection))
{
var sql = "DELETE FROM ModelItemReferences WHERE ReferenceId = @ReferenceId";
if (!string.IsNullOrEmpty(referenceType))
{
sql += " AND ReferenceType = @ReferenceType";
cmd.Parameters.AddWithValue("@ReferenceType", referenceType);
}
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("@ReferenceId", referenceId);
cmd.ExecuteNonQuery();
}
});
}
#endregion
/// <summary>

View File

@ -2273,6 +2273,28 @@ namespace NavisworksTransport.UI.WPF.ViewModels
}
}
/// <summary>
/// 获取运动物体的 PathId 信息
/// </summary>
private (int ModelIndex, string PathId) GetVehiclePathIdInfo()
{
try
{
if (SelectedAnimatedObject == null)
{
return (0, null);
}
var pathId = Application.ActiveDocument.Models.CreatePathId(SelectedAnimatedObject);
return (pathId.ModelIndex, pathId.PathId);
}
catch (Exception ex)
{
LogManager.Warning($"[批处理] 无法获取运动对象的 PathId: {SelectedAnimatedObject.DisplayName}, 错误: {ex.Message}");
return (0, null);
}
}
private List<ModelItem> GetValidManualCollisionTargets(bool pruneInvalidEntries = false)
{
var validItems = new List<ModelItem>();
@ -3528,7 +3550,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
PathRouteName = CurrentPathRoute.Name,
Status = BatchQueueStatus.Pending,
CreatedTime = DateTime.Now,
// 动画配置
FrameRate = _animationFrameRate,
DurationSeconds = AnimationDuration,
@ -3541,39 +3563,81 @@ namespace NavisworksTransport.UI.WPF.ViewModels
VirtualVehicleLength = VirtualVehicleLength,
VirtualVehicleWidth = VirtualVehicleWidth,
VirtualVehicleHeight = VirtualVehicleHeight,
VehicleObjectId = UseVirtualVehicle ? null : SelectedAnimatedObject?.ToString(),
VehicleObjectName = UseVirtualVehicle ? null : SelectedAnimatedObject?.DisplayName,
// 被检测项配置
DetectAllObjects = !IsManualCollisionTargetEnabled,
DetectionItems = IsManualCollisionTargetEnabled
? GetValidManualCollisionTargets(pruneInvalidEntries: true).Select(t => t.ToString()).ToList()
: new List<string>(),
// 角度修正配置
ObjectRotationCorrection = _objectRotationCorrection
};
// 调用批处理管理器添加到队列
var batchQueueManager = Core.BatchQueueManager.Instance;
// 确保BatchQueueManager有PathPlanningManager用于获取数据库
if (_pathPlanningManager != null)
{
batchQueueManager.SetPathPlanningManager(_pathPlanningManager);
}
var itemId = await batchQueueManager.AddQueueItemAsync(queueItem);
// 存储运动物体到 ModelItemReferences 表
if (!UseVirtualVehicle && SelectedAnimatedObject != null)
{
var pathIdInfo = GetVehiclePathIdInfo();
if (pathIdInfo.ModelIndex != 0 && !string.IsNullOrEmpty(pathIdInfo.PathId))
{
var db = _pathPlanningManager?.GetPathDatabase();
if (db != null)
{
await db.AddModelItemReferenceAsync(
itemId,
"BatchQueueItem",
pathIdInfo.ModelIndex,
pathIdInfo.PathId,
SelectedAnimatedObject.DisplayName,
SelectedAnimatedObject.DisplayName,
"Vehicle"
);
LogManager.Info($"[批处理] 已存储运动物体: {SelectedAnimatedObject.DisplayName}");
}
}
}
// 存储手工指定的碰撞检测目标到 ModelItemReferences 表
if (IsManualCollisionTargetEnabled)
{
var db = _pathPlanningManager?.GetPathDatabase();
if (db != null)
{
var validItems = GetValidManualCollisionTargets(pruneInvalidEntries: true);
foreach (var item in validItems)
{
var pathId = Application.ActiveDocument.Models.CreatePathId(item);
await db.AddModelItemReferenceAsync(
itemId,
"BatchQueueItem",
pathId.ModelIndex,
pathId.PathId,
item.DisplayName,
item.DisplayName,
"CollisionTarget"
);
}
LogManager.Info($"[批处理] 已存储 {validItems.Count} 个手工指定碰撞目标");
}
}
LogManager.Info($"[批处理] 已创建队列项: {queueItem.PathRouteName}, " +
$"虚拟车辆: {queueItem.IsVirtualVehicle}, " +
$"帧率: {queueItem.FrameRate}, " +
$"时长: {queueItem.DurationSeconds:F2}秒, " +
$"角度修正: {queueItem.ObjectRotationCorrection:F1}°, " +
$"ID: {itemId}");
UpdateMainStatus($"已添加到批处理队列: {queueItem.PathRouteName}");
// 显示成功提示
System.Windows.MessageBox.Show(
$"已成功添加到批处理队列:{queueItem.PathRouteName}\n" +
@ -3586,7 +3650,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
LogManager.Error($"添加到批处理失败: {ex.Message}", ex);
UpdateMainStatus($"添加失败: {ex.Message}");
// 显示失败提示
System.Windows.MessageBox.Show(
$"添加到批处理队列失败:{ex.Message}",

View File

@ -140,7 +140,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
// 初始化命令
ExecuteQueueCommand = new RelayCommand(async () => await ExecuteQueueAsync(), () => CanExecuteQueue);
StopExecutionCommand = new RelayCommand(StopExecution, () => CanStopExecution);
StopExecutionCommand = new RelayCommand(StopExecution, () => true);
DeleteItemCommand = new RelayCommand(async () => await DeleteItemAsync(), () => CanDeleteItem);
ViewReportCommand = new RelayCommand(async () => await ViewReportAsync(), () => CanViewReport);
RefreshCommand = new RelayCommand(async () => await LoadQueueItemsAsync());

View File

@ -54,6 +54,7 @@ NavisworksTransport 批处理队列管理页签视图 - 采用与其他页签一
Style="{StaticResource ActionButtonStyle}"/>
<Button Content="停止执行"
Command="{Binding StopExecutionCommand}"
IsEnabled="True"
Style="{StaticResource ActionButtonStyle}"/>
<Button Content="删除选中"
Command="{Binding DeleteItemCommand}"