aierda 2023-11-02 16:00 采纳率: 72.1%
浏览 71
已结题

InvokeCommandAction带多种参数的问题

问题描述:直接上代码,具体情况,代码行间有描述

<StackPanel Orientation="Vertical" Margin="0 0" Name="RootElement">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <i:InvokeCommandAction Command="{Binding MouseEnterCommand}" />
        </i:EventTrigger>
                /*
            给StackPanel绑定三个鼠标事件(MouseEnter、MouseMove、MouseLeave),每个InvokeCommandAction
                        要带两种参数,
             一种是MouseEventArgs,为此将PassEventArgsToCommand设置为True。
             另外一种是附加参数,如果是附加参数只有一个,那么可以使用CommandParameter进行处理;但是考虑到有2个
                         或更多,所以使用了MultiBinding来处理附加参数,如下所示RootElement,WelcomeBorder都是UI元素,它们
                        都是作为附加参数来进行传递的。
            换言之,有两种参数(MouseEventArgs + 附加参数),共三个参数
                     (MouseEventArgs+RootElement+WelcomeBorder)需要传到ViewModel中去。
            
            但是让我困惑的是,我不知道如何在ViewModel中去接收界面中传过来参数,以及如何去触发鼠标事件
                      (如果只传一种参数,我知道如何在ViewModel中进行处理,这种复杂的,让我一时糊涂了)
        */
        <i:EventTrigger EventName="MouseMove">
            <i:InvokeCommandAction Command="{Binding MouseMoveCommand}" PassEventArgsToCommand="True">
                <i:InvokeCommandAction.CommandParameter>
                    <MultiBinding Converter="{StaticResource ResourceKey=ObjectConvert}" Mode="TwoWay">
                        <MultiBinding.Bindings>
                            <Binding ElementName="RootElement" />
                            <Binding ElementName="WelcomeBorder" />
                        </MultiBinding.Bindings>
                    </MultiBinding>
                </i:InvokeCommandAction.CommandParameter>
            </i:InvokeCommandAction>
        </i:EventTrigger>
        <i:EventTrigger EventName="MouseLeave">
            <i:InvokeCommandAction Command="{Binding MouseLeaveCommand}">
            </i:InvokeCommandAction>
        </i:EventTrigger>
    </i:Interaction.Triggers>

    <Border Name="WelcomeBorder" Margin="0 500 0 60" Padding="5" BorderThickness="1" BorderBrush="Black" Background="Black" CornerRadius="40" Width="1000">
        <TextBlock Style="{StaticResource BaseMsgTextBlock}" FontSize="{Binding FontSizeScale,Converter={StaticResource CalcFontSize}, ConverterParameter=60}"
               FontWeight="Bold" Text="{langs:Lang Key={x:Static langs:Lang.WelcomeText}}"  Width="1000" TextAlignment="Center">
        </TextBlock>
    </Border>
</StackPanel>

我需要在InvokeCommandAction带多种参数进行传递,然后我不知道在viewmodel中如何去接收参数以及触发事件。
为此我查阅了一些资料,发现有一篇文章涉及这个问题,可惜的是,偏偏没有viewmodel层面的代码,这篇文章的网址为
https://blog.csdn.net/weixin_43235128/article/details/128345251
这篇文章中提到的“方式二”与我的情形甚是吻合,但是我不清楚,在viewmodel层面如何去处理。

提出问题: 签于我的这种情形,跟大家请教解决方案,期待大家的指点,感谢!

  • 写回答

14条回答 默认 最新

  • 社区专家-Monster-XH 2023-11-02 16:01
    关注

    基于Monster 组和AIGC的调写:

    • 在 WPF MVVM 模式中,InvokeCommandAction 可以用来将 View 的事件绑定到 ViewModel 的命令上。在你的情况中想要同时传递 MouseEventArgs 和其他 UI 元素作为参数到命令中。通过一个参数对象来实现,这个参数对象会包含所有需要的参数。这就要求你创建一个自定义的参数类,并且在 XAML 里使用一个 MultiValueConverter 来将这些参数绑定到一个对象实例上。

    • 先创建一个自定义的参数类和一个 MultiValueConverter。参数类可以像这样定义:

    public class MouseActionCommandParameter
    {
        public MouseEventArgs MouseEventArgs { get; set; }
        public UIElement RootElement { get; set; }
        public UIElement WelcomeBorder { get; set; }
    }
    
    • 然后创建 MultiValueConverter
    public class MouseActionParameterConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length > 1 && values[0] is MouseEventArgs mouseArgs && values[1] is UIElement rootElement && values[2] is UIElement welcomeBorder)
            {
                return new MouseActionCommandParameter
                {
                    MouseEventArgs = mouseArgs,
                    RootElement = rootElement,
                    WelcomeBorder = welcomeBorder
                };
            }
            return null;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    
    • 在 ViewModel 中,你要定义命令的类型从 ICommand 更改为 ICommand<MouseActionCommandParameter> 或者你可以用 DelegateCommand<MouseActionCommandParameter>,如果你用的是 Prism 库:
    public class YourViewModel
    {
        public ICommand MouseMoveCommand { get; private set; }
    
        public YourViewModel()
        {
            MouseMoveCommand = new DelegateCommand<MouseActionCommandParameter>(OnMouseMove);
        }
    
        private void OnMouseMove(MouseActionCommandParameter parameter)
        {
            // 你现在可以访问 parameter.MouseEventArgs, parameter.RootElement 和 parameter.WelcomeBorder
        }
    }
    
    • 在 XAML 中你要确保你的 MultiBindingMouseActionParameterConverter 和新定义的参数类型相匹配:
    <i:EventTrigger EventName="MouseMove">
        <i:InvokeCommandAction Command="{Binding MouseMoveCommand}" PassEventArgsToCommand="True">
            <i:InvokeCommandAction.CommandParameter>
                <MultiBinding Converter="{StaticResource MouseActionParameterConverter}">
                    <Binding Path="MouseEventArgs" />
                    <Binding ElementName="RootElement" />
                    <Binding ElementName="WelcomeBorder" />
                </MultiBinding>
            </i:InvokeCommandAction.CommandParameter>
        </i:InvokeCommandAction>
    </i:EventTrigger>
    

    注意:确保你在资源字典中定义了 MouseActionParameterConverter

    <Window.Resources>
        <local:MouseActionParameterConverter x:Key="MouseActionParameterConverter" />
    </Window.Resources>
    
    • 通过这种方式,你可以将多个参数封装到一个对象中,并通过命令传递到 ViewModel 中。在 ViewModel 的命令处理方法中,你可以访问所有的参数。
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(13条)

报告相同问题?

问题事件

  • 系统已结题 11月14日
  • 已采纳回答 11月6日
  • 修改了问题 11月2日
  • 创建了问题 11月2日