ToolbarTray 工具栏内的按钮与 Caliburn 事件有关

Button inside ToolbarTray Toolbar problem with Caliburn Event

我没有找到用 Caliburn 激活按钮的解决方案。正如您在 MainToolBarTrayView.xaml 程序中看到的那样,按钮位于 toolbarTray/ToolBar 内。

因此,当我单击同名按钮时,我将执行函数 AlignBottom(例如)

我不明白为什么它不起作用,而且我在网上也没有看到类似的问题。可能是我做错了什么..谢谢你的帮助

我在 Github CockpitBuilder

上有我的全球项目

欢迎任何帮助....

MainToolBarTrayView.xaml

<UserControl x:Class="CockpitBuilder.Views.Main.ToolBarTray.MainToolBarTrayView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:common="clr-namespace:CockpitBuilder.Common.Caliburn"
             xmlns:cal="http://www.caliburnproject.org"
             xmlns:local="clr-namespace:CockpitBuilder.Views.Main.ToolBarTray"
             mc:Ignorable="d" 
             d:DesignHeight="30" d:DesignWidth="800">
    <Grid>
        <ToolBarTray  x:Name="ToolBar" IsLocked="True" Background="Transparent" >
            <ToolBar Height="28" Background="Transparent"  >
                <Button x:Name="MoveForward" >
                    <Image Source="{StaticResource BringForwardIcon}" />
                    <Button.ToolTip>Bring control forward so it displays on top of other controls.</Button.ToolTip>
                </Button>
                <Button x:Name="MoveBack">
                    <Image Source="{StaticResource SendBackIcon}" />
                    <Button.ToolTip>Send control back so it displays under other controls.</Button.ToolTip>
                </Button>
                <Separator />
                <Button x:Name="AlignTop">
                    <Image Source="{StaticResource AlignTop}" />
                    <Button.ToolTip>Align selected controls to the top of the first selected control.</Button.ToolTip>
                </Button>
                <Button  x:Name="AlignBottom"  >

                    <Image Source="{StaticResource AlignBottom}"  />
                    <Button.ToolTip>Align selected controls to the bottom of the first selected control.</Button.ToolTip>
                </Button>
                <Button x:Name="AlignHorizontalCenter">
                    <Image Source="{StaticResource AlignHCenter}" />
                    <Button.ToolTip>Align selected controls to the vertical center of the first selected control.</Button.ToolTip>
                </Button>
                <Button x:Name="AlignLeft">
                    <Image Source="{StaticResource AlignLeft}" />
                    <Button.ToolTip>Align selected controls to the left of the first selected control.</Button.ToolTip>
                </Button>
                <Button x:Name="AlignRight">
                    <Image Source="{StaticResource AlignRight}" />
                    <Button.ToolTip>Align selected controls to the right of the first selected control.</Button.ToolTip>
                </Button>
                <Button x:Name="AlignVerticalCenter">
                    <Image Source="{StaticResource AlignVCenter}" />
                    <Button.ToolTip>Align selected controls to the horizontal center of the first selected control.</Button.ToolTip>
                </Button>
                <Separator />
                <Button x:Name="DistributeHorizontalCenter">
                    <Image Source="{StaticResource DistributeHorizontal}" />
                    <Button.ToolTip>Distribute horizontally selected controls evenly spaced on ceneter.</Button.ToolTip>
                </Button>
                <Button x:Name="DistributeVerticalCenter">
                    <Image Source="{StaticResource DistributeVertical}" />
                    <Button.ToolTip>Distribute vertically selected controls evenly spaced on ceneter.</Button.ToolTip>
                </Button>
                <Separator />
                <Button x:Name="SpaceHorizontal">
                    <Image Source="{StaticResource SpaceHorizontal}" />
                    <Button.ToolTip>Space evenly selected controls horizontaly.</Button.ToolTip>
                </Button>
                <Button x:Name="SpaceVertical">
                    <Image Source="{StaticResource SpaceVertical}" />
                    <Button.ToolTip>Space evenly selected controls verticaly.</Button.ToolTip>
                </Button>
            </ToolBar>

        </ToolBarTray>
    </Grid>
</UserControl>

MainToolBarTrayViewModel.cs

using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using IEventAggregator = CockpitBuilder.Core.Common.Events.IEventAggregator;

namespace CockpitBuilder.Views.Main.ToolBarTray
{
    public class MainToolBarTrayViewModel : Screen
    {
        private readonly IEventAggregator eventAggregator;
        private bool _canAlignBottom;

        public MainToolBarTrayViewModel(IEventAggregator eventAggregator)
        {

        }

        public void AlignBottom()
        {

        }

        bool canAlignBottom
        {
            get => _canAlignBottom;
            set
            {
                _canAlignBottom = value;
                NotifyOfPropertyChange(() => canAlignBottom);
            }
        }

    }
}

MainShellViewModel.cs是加载MainToolBarTrayViewModel.cs

的程序
using Caliburn.Micro;
using CockpitBuilder.Common.AvalonDock;
using CockpitBuilder.Core.Common;
using CockpitBuilder.Core.Persistence;
using CockpitBuilder.Core.Persistence.Paths;
using CockpitBuilder.Events;
using CockpitBuilder.Result;
using CockpitBuilder.Views.Main.DockPanel;
using CockpitBuilder.Views.Main.DockPanel.Panels;
using CockpitBuilder.Views.Main.Menu;
using CockpitBuilder.Views.Main.ToolBarTray;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using Xceed.Wpf.AvalonDock;
using Xceed.Wpf.AvalonDock.Layout.Serialization;
using IEventAggregator = CockpitBuilder.Core.Common.Events.IEventAggregator;

namespace CockpitBuilder.Shells
{
    public class MainShellViewModel : ShellPresentationModel, Core.Common.Events.IHandle<ExitingEvent>, Core.Common.Events.IHandle<ScriptDocumentAddedEvent>
    {
        private readonly IEventAggregator eventAggregator;
        private readonly IPersistanceManager persistanceManager;
        private readonly ISettingsManager settingsManager;
        private readonly IFileSystem fileSystem;
        private readonly IPaths paths;

        private const string dockingConfig = "layout.config";
        public MainShellViewModel(IResultFactory resultFactory,
                                  IEventAggregator eventAggregator,
                                  MainMenuViewModel mainMenuViewModel,
                                  MainToolBarTrayViewModel mainToolBarViewModel,
                                  IEnumerable<PanelViewModel> panels,
                                  ISettingsManager settingsManager,
                                  IFileSystem fileSystem,
                                  IPersistanceManager persistanceManager,
                                  IPaths paths,
                                  IPortable portable
            )
            : base(resultFactory)
        {
            this.eventAggregator = eventAggregator;
            eventAggregator.Subscribe(this);

            this.persistanceManager = persistanceManager;
            this.settingsManager = settingsManager;
            this.fileSystem = fileSystem;
            this.paths = paths;

            Menu = mainMenuViewModel;
            ToolBarTray = mainToolBarViewModel;

            Scripts = new BindableCollection<MonitorViewModel>();
            Tools = new BindableCollection<PanelViewModel>(panels);

           mainMenuViewModel.NewProfile();
        }

        protected override void OnViewLoaded(object view)
        {
            base.OnViewLoaded(view);
            InitDocking();
            //parser.ParseAndExecute();
            //eventAggregator.Publish(new StartedEvent());
        }

        private void InitDocking()
        {
            var path = paths.GetDataPath(dockingConfig);

            if (!fileSystem.Exists(path)) return;
            try
            {
                var layoutSerializer = new XmlLayoutSerializer(DockingManager);
                layoutSerializer.Deserialize(path);
            }
            catch
            {
                fileSystem.Delete(path);
            }
        }

        //public IEnumerable<IResult> DocumentClosing(ScriptEditorViewModel document, DocumentClosingEventArgs e)
        //{
        //    return Result.Coroutinify(HandleScriptClosing(document), () => e.Cancel = true);
        //}

        //public void DocumentClosed(ScriptEditorViewModel document)
        //{
        //    Scripts.Remove(document);
        //}

        private IEnumerable<IResult> HandleScriptClosing(bool v = false)
        {
            if (v)
            {
                var message = Result.ShowMessageBox("", "", MessageBoxButton.YesNoCancel);
                yield return message;
            }
        }
        protected override IEnumerable<IResult> CanClose()
        {
            var r = HandleScriptClosing(false);
            foreach (var result in r)
            {
                yield return result;
            }

            eventAggregator.Publish(new ExitingEvent());


        }
        private DockingManager DockingManager
        {
            get { return (this.GetView() as IDockingManagerSource).DockingManager; }
        }

        private PanelViewModel activeDocument;
        public PanelViewModel ActiveDocument
        {
            get { return activeDocument; }
            set
            {

                if (value == null || value.IsFileContent)
                {
                    activeDocument = value;
                    NotifyOfPropertyChange(() => ActiveDocument);
                    eventAggregator.Publish(new ActiveScriptDocumentChangedEvent(value));
                }
            }
        }
        public MainMenuViewModel Menu { get; set; }
        public MainToolBarTrayViewModel ToolBarTray { get; set; }

        public BindableCollection<MonitorViewModel> Scripts { get; set; }
        public BindableCollection<PanelViewModel> Tools { get; set; }


        public void Handle(ScriptDocumentAddedEvent message)
        {
            if (message.toDelete)
            {
                Scripts.Remove(message.Document);
                return;
            }

            var script = Scripts.FirstOrDefault(s => s.ContentId == message.Document.ContentId);

            if (script == null)
            {
                script = message.Document;
                Scripts.Add(script);
            }

            script.IsActive = true;

            ActiveDocument = message.Document;
        }


        public void Handle(ExitingEvent message)
        {
            persistanceManager.Save();
            var layoutSerializer = new XmlLayoutSerializer(DockingManager);
            layoutSerializer.Serialize(paths.GetDataPath(dockingConfig));
        }
    }
}

我找到了解决问题的办法:

我只是 link 在 xaml 中命令并保持按钮控件未命名(我想避免与 caliburn 交互)

在MainToolBarTrayView.xaml

            <Button  Command="{Binding AlignBottom}" >
                <Image Source="{StaticResource AlignBottom}"  />
                <Button.ToolTip>Align selected controls to the bottom of the first selected control.</Button.ToolTip>
            </Button>

然后我在 viewModel 中定义所有命令(使用中继命令) 在 MainToolBarTrayViewModel.cs

using Caliburn.Micro;                                                                    
using System;                                                                            
using System.Windows.Input;                                                              
using IEventAggregator = CockpitBuilder.Core.Common.Events.IEventAggregator;             

namespace CockpitBuilder.Views.Main.ToolBarTray                                          
{                                                                                        
    public class MainToolBarTrayViewModel : Screen                                       
    {                                                                                    
        private readonly IEventAggregator eventAggregator;                               
        private bool _canAlignBottom;                                                    
        public ICommand AlignBottom { get; private set; }                                
        public MainToolBarTrayViewModel(IEventAggregator eventAggregator)                
        {                                                                                
            AlignBottom = new RelayCommand(o => cmdAlignBottom(), o => true);            
        }                                                                                

        public void cmdAlignBottom()                                                     
        {                                                                                

        }                                                                                                                                                                                                                                                                                                                                                    
    }                                                                                    


    public class RelayCommand : ICommand                                                 
    {                                                                                    
        private Action<object> execute;                                                  
        private Func<object, bool> canExecute;                                           

        public event EventHandler CanExecuteChanged                                      
        {                                                                                
            add { CommandManager.RequerySuggested += value; }                            
            remove { CommandManager.RequerySuggested -= value; }                         
        }                                                                                

        public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
        {                                                                                
            this.execute = execute;                                                      
            this.canExecute = canExecute;                                                
        }                                                                                

        public bool CanExecute(object parameter)                                         
        {                                                                                
            return this.canExecute == null || this.canExecute(parameter);                
        }                                                                                

        public void Execute(object parameter)                                            
        {                                                                                
            this.execute(parameter);                                                     
        }                                                                                
    }                                                                                    
}