zoukankan      html  css  js  c++  java
  • 基于WPF系统框架设计(9)-多值绑定之IMultiValueConverter

    应用场景

    我想把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="ImagesGreen.png" LargeIcon="ImagesGreenLarge.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层了。眨眼

  • 相关阅读:
    Nginx 学习笔记(一)如何配置一个安全的HTTPS网站服务器
    Ubuntu(16.04.2)学习笔记(一)如何解决dpkg: error processing install-info
    Linux 命令详解(八)Systemd 入门教程:实战篇
    Linux 命令详解(七)Systemd 入门教程:命令篇
    Linux 命令详解(六)Linux 守护进程的启动方法
    PHP7 学习笔记(四)PHP PSR-4 Autoloader 自动加载
    PHP7 学习笔记(三)关于PHP7如何安装调试工具Xdebug扩展以及Zephir的问题
    WorkerMan 入门学习之(三)基础教程-Timer类的使用
    WorkerMan 入门学习之(二)基础教程-Connection类的使用
    数字证书相关知识结构PKI/PMI基本概念、组成部分、工作原理
  • 原文地址:https://www.cnblogs.com/aganqin/p/3277075.html
Copyright © 2011-2022 走看看