随笔 - 27  文章 - 0  评论 - 316  阅读 - 15万 

应用场景

我想把View层的一个布局控件和功能按钮传到ViewModel层,达到动态变更布局,同时灵活获取功能按钮的属性,让View和ViewModel完全分离,而不受View层影响。

最后我想到使用IMultiValueConverter实现多参传入ViewModel层来解决,不知道还有没有更好的办法?

基本原理:要将值转换器与 MultiBinding 关联,请创建一个实现 IMultiValueConverter 接口的类,然后实现 Convert 和 ConvertBack 方法。
集合中的各个绑定可以具有自己的值转换器。

使用 MultiBinding,您可以将绑定目标属性绑定到源属性列表,然后应用逻辑以使用给定的输入生成值。

实现步骤

    添加继承IMultiValueConverter接口的类并实现接口

    注意:返回的values一定要转为数组列表values.ToArray()

参考如下代码

复制代码
using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace TLAgent.SecurityManager.WPF.MultiBindings
{
  public class DataConverter : IMultiValueConverter
  {
    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType,
      object parameter, System.Globalization.CultureInfo culture)
    {
        return values.ToArray() ;
    }

    public object[] ConvertBack(object value, Type[] targetTypes,
      object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
  }
}
复制代码

在XAML中进行多参绑定

复制代码
<Fluent:Button Header="添加用户" Icon="Images\Green.png" LargeIcon="Images\GreenLarge.png" x:Name="BtnAddUser" Command="{Binding AddUserCommand}">
                        <Fluent:Button.CommandParameter>
                            <MultiBinding Converter="{ StaticResource ResourceKey=dataConverter}" Mode="TwoWay">
                                <MultiBinding.Bindings>
                                    <Binding ElementName="BtnAddUser"/>
                                    <Binding ElementName="dockManager "/>
                                </MultiBinding.Bindings>
                            </MultiBinding>
                        </Fluent:Button.CommandParameter>
                        
                    </Fluent:Button>
复制代码
<Window.Resources>
        <local:DataConverter x:Key="dataConverter"/>
</Window.Resources>

ViewModel中进行命令和方法绑定

注意:DelegateCommand<object[]>的参数是要支持对象数组。

复制代码
using System;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;
using Xceed.Wpf.AvalonDock;
using Xceed.Wpf.AvalonDock.Layout;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
using UserControl = System.Windows.Controls.UserControl;

namespace TLAgent.SecurityManager.WPF.ViewModels
{
    public class MainWindowViewModel : NotificationObject
    {
        public ICommand ExitSystemCommand { get; set; }

        public ICommand AddUserCommand { get; set; }

        public ICommand OpenHelpCommand { get; set; }

        public MainWindowViewModel()
        {
            ExitSystemCommand = new DelegateCommand(this.OnExit);
            OpenHelpCommand = new DelegateCommand(this.OnOpenSupport);
            AddUserCommand = new DelegateCommand<object[]>(this.AddUser);
        }


        private void CreateTab(DockingManager dockManager, string tabName, UserControl control)
        {
            var firstDocumentPane = dockManager.Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
            if (firstDocumentPane != null)
            {
                LayoutDocument doc2 = new LayoutDocument();
                doc2.Title = tabName;
                doc2.Content = control;
                doc2.IsActive = true;
                firstDocumentPane.Children.Add(doc2);
            }
        }

        private void OnExit()
        {
            MessageBoxResult result = MessageBox.Show("确定要退出系统吗?", "确认消息", MessageBoxButton.OKCancel, MessageBoxImage.Question);
            if (result == MessageBoxResult.OK)
            {
                Application.Current.Shutdown();
            }
        }

        private void OnOpenSupport()
        {
            MessageBox.Show("帮助窗口!");
        }
        
       private void AddUser(object[] objParam)
       {
            if (objParam.Length == 2)
            {
                Fluent.Button button = (Fluent.Button)objParam[0];
                DockingManager dockingManager = (DockingManager)objParam[1];
                UserControl control;
                control = new UserControl1();

                CreateTab(dockingManager, button.Header.ToString(), control);
            }
      }
    }
}
复制代码

控件绑定

这样就可以在方法AddUer的参数中取得View层绑定的两个控件:

<MultiBinding.Bindings>
     <Binding ElementName="BtnAddUser"/>
     <Binding ElementName="dockManager "/>
</MultiBinding.Bindings>

这样基本就实现了从View层传多个对象到ViewModel层了。眨眼

posted on   aganqin  阅读(3673)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示