英文:
Does a Revit command have to be passed as a relay command using WPF and MVVM pattern
问题
以下是您提供的代码的中文翻译:
我有一些外部命令,当通过Revit中的下拉按钮调用时,它们可以完美运行。我尝试通过在使用MVVM模式的WPF窗口中创建命令列表来升级代码 - 主要是如此。在这些情况下,没有模型,而是一个与Revit文件通信的服务。以下是一个执行调用以删除材料的示例服务:
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace DevTools.Services.Cleaner
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
[Journaling(JournalingMode.NoCommandData)]
public class PurgeAllMaterialsService : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
var uiDoc = commandData.Application.ActiveUIDocument;
var doc = uiDoc.Document;
try
{
using Transaction trans = new(doc, "删除所有材料");
var allMaterials = new FilteredElementCollector(doc)
.OfClass(typeof(Material))
.ToElementIds();
var count = 0;
trans.Start();
foreach (var id in allMaterials)
{
try
{
var m = doc.GetElement(id) as Material;
{
uiDoc.Document.Delete(id);
count++;
}
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
trans.Commit();
TaskDialog.Show("删除所有材料", count + "个材料已被删除");
return Result.Succeeded;
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
return Result.Cancelled;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
}
}
视图模型在RelayCommand中调用服务:
using CommunityToolkit.Mvvm.Input;
using DevTools.Services.Cleaner;
namespace DevTools.ViewModels
{
public partial class CleanerViewModel
{
private PurgeAllMaterialsService _purgeAllMaterialsService;
[RelayCommand]
private void PurgeAllMaterials()
{
_purgeAllMaterialsService = new PurgeAllMaterialsService();
}
}
}
命令将服务传递给视图:
using Autodesk.Revit.Attributes;
using DevTools.Services.Cleaner;
using DevTools.ViewModels;
using DevTools.Views;
using Nice3point.Revit.Toolkit.External;
namespace DevTools.Commands
{
[UsedImplicitly]
[Transaction(TransactionMode.Manual)]
public class CleanWindowCommand : ExternalCommand
{
public override void Execute()
{
var viewModel = new CleanerViewModel();
var view = new CleanerPage(viewModel);
view.ShowDialog();
}
}
}
在视图中,通过按钮调用命令,如下所示:
<Button Content="清除材料"
Command="{Binding PurgeAllMaterialsCommand, Mode=OneWay}"
Width="200"
Height="28"
Margin="0,10,0,0"
BorderBrush="Transparent"
Background="{StaticResource HeaderBackgroundBrush}"
Foreground="{StaticResource LightBrush}" />
问题是按钮未执行命令。缺少什么?WPF窗口是否阻止了命令的发送?
英文:
I have a few external commands that work perfectly when called by a pulldown button in Revit. I was attempting to upgrade the code by creating a list of commands in a WPF window using the MVVM pattern - mostly. There are no models in these cases instead a service that speaks to the Revit file. Below is an example of a service executes a call to remove materials:
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace DevTools.Services.Cleaner
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
[Journaling(JournalingMode.NoCommandData)]
public class PurgeAllMaterialsService : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
var uiDoc = commandData.Application.ActiveUIDocument;
var doc = uiDoc.Document;
try
{
using Transaction trans = new(doc, "Delete all materials");
var allMaterials = new FilteredElementCollector(doc)
.OfClass(typeof(Material))
.ToElementIds();
var count = 0;
trans.Start();
foreach (var id in allMaterials)
{
try
{
var m = doc.GetElement(id) as Material;
{
uiDoc.Document.Delete(id);
count++;
}
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
trans.Commit();
TaskDialog.Show("Delete All Materials", count + " materials have been deleted");
return Result.Succeeded;
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
return Result.Cancelled;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
}
}
The view-model calls the service in a relay command
using CommunityToolkit.Mvvm.Input;
using DevTools.Services.Cleaner;
namespace DevTools.ViewModels
{
public partial class CleanerViewModel
{
private PurgeAllMaterialsService _purgeAllMaterialsService;
[RelayCommand]
private void PurgeAllMaterials()
{
_purgeAllMaterialsService = new PurgeAllMaterialsService();
}
}
}
and the command passes the service to the view.
using Autodesk.Revit.Attributes;
using DevTools.Services.Cleaner;
using DevTools.ViewModels;
using DevTools.Views;
using Nice3point.Revit.Toolkit.External;
namespace DevTools.Commands
{
[UsedImplicitly]
[Transaction(TransactionMode.Manual)]
public class CleanWindowCommand : ExternalCommand
{
public override void Execute()
{
var viewModel = new CleanerViewModel();
var view = new CleanerPage(viewModel);
view.ShowDialog();
}
}
}
in the view the command is called by a button like so.
<Button Content="Purge Materials"
Command="{Binding PurgeAllMaterialsCommand, Mode=OneWay}"
Width="200"
Height="28"
Margin="0,10,0,0"
BorderBrush="Transparent"
Background="{StaticResource HeaderBackgroundBrush}"
Foreground="{StaticResource LightBrush}" />
The problem is the button does not execute the command. What is missing? Is the WPF window blocking the command bein sent?
答案1
得分: 1
"The Button
的Command
属性必须设置或绑定到实现System.Windows.Input.ICommand
接口的对象。
因此,您的视图模型的PurgeMaterialCommand
属性应返回一个ICommand
实现。然后,当您点击按钮调用该命令时,将调用Execute(object parameter)
方法。"
英文:
The Command
property of the Button
must be set or bound to an object that implements the System.Windows.Input.ICommand
interface.
So the PurgeMaterialCommand
property of your view model should return an ICommand
implementation. The Execute(object parameter)
method will then be called when you invoke the command by clicking on the button.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论