Revit命令是否必须以WPF和MVVM模式使用中继命令传递

huangapple go评论65阅读模式
英文:

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, &quot;Delete all materials&quot;);

            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(&quot;Delete All Materials&quot;, count + &quot; materials have been deleted&quot;);
            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.

&lt;Button Content=&quot;Purge Materials&quot;
        Command=&quot;{Binding PurgeAllMaterialsCommand, Mode=OneWay}&quot;
        Width=&quot;200&quot;
        Height=&quot;28&quot;
        Margin=&quot;0,10,0,0&quot;
        BorderBrush=&quot;Transparent&quot;
        Background=&quot;{StaticResource HeaderBackgroundBrush}&quot;
        Foreground=&quot;{StaticResource LightBrush}&quot; /&gt;

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 ButtonCommand属性必须设置或绑定到实现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.

huangapple
  • 本文由 发表于 2023年5月17日 18:13:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76270983.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定