WPF .netCore使用MVVM


WPF MVVM模式一直没怎么用过,.net5正式版就要出来了,趁这个时间看看各个微软的前后端.netCore的功能,使用.netCore下WPF实现一个简单的从数据库读取数据显示功能,

示例主要用到了按钮,编辑框,树控件,列表控件, 代码东拼西凑的,只贴几个片段。

1、XAML


    
        
    
    
        
            
            
            
        
        
            
                
                    
                    
                    
                
                
                
                
            
            
            
        

        
        
            
                
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                    
                
            
            
                
                
            
        
        
    

2、DataBaseModel.cs

using NEasyCode.Entity;
using NEasyCode.Util;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;

namespace NEasyCode
{
    public class DataBaseViewModel : INotifyPropertyChanged
    {
        #region Fields
        private string _searchText;
        private ObservableCollection _resultList;
        #endregion

        #region Properties
        private ObservableCollection tableInfoList;
        public ObservableCollection TableInfoList 
        { 
            get {
                return tableInfoList;
            } 
            set
            {
                tableInfoList = value;
                RaisePropertyChanged("TableInfoList");
            } 
        }
        public ObservableCollection TableList { get; set; } = new ObservableCollection();
        public ObservableCollection TreeViewItems { get; set; } = new ObservableCollection();
        // 查询关键字
        public string SearchText
        {
            get { return _searchText; }
            set
            {
                _searchText = value;
                RaisePropertyChanged("SearchText");
            }
        }
        public ICommand QueryCommand
        {
            get { return new QueryCommand(SearchTable, CanSearching); }
        }


        #endregion

        #region Construction
        public DataBaseViewModel()
        {
            SearchTable();
            ViewTableInfo("dghr_userinfo");
        }


        #endregion
        
        #region Command Handler
        /// 
        /// 查看表信息
        /// 
        /// 
        public void ViewTableInfo(string tableName)
        {
            //TableInfoList.Clear();
            TableInfoList = DbUtil.GetTableProp(tableName).ToObservableCollection();
            //_resultList = TableInfoList;
        }
        /// 
        /// 查找表
        /// 
        public void SearchTable()
        {
            TableList.Clear();
            var tableList= DbUtil.GetAllDataBase().ToObservableCollection();
            if (string.IsNullOrWhiteSpace(SearchText))
            {
                TableList = tableList;
            }
            else
            {
               
                foreach (string p in tableList)
                {
                    if (p.Contains(SearchText))
                    {
                        TableList.Add(p);
                    }
                }
            }
            TreeViewItems.Clear();
            for (int i = 0; i < TableList.Count; i++)
            {
                TreeViewItem item = new TreeViewItem();
                item.Header = TableList[i];
                item.Selected += Item_Selected;
                item.MouseDoubleClick += Item_MouseDoubleClick;
                
                TreeViewItems.Add(item);
            }
        }

        private void Item_Selected(object sender, System.Windows.RoutedEventArgs e)
        {
            var v= ((TreeViewItem)(e.Source)).Header.ToString();
            ViewTableInfo(v);
        }

        private void Item_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            //ViewTableInfo(e.ToString)
        }

        public bool CanSearching()
        {
            return true;
        }


        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;


        #endregion

        #region Methods
        private void RaisePropertyChanged(string propertyName)
        {
            // take a copy to prevent thread issues
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

}

3、Command

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Input;

namespace NEasyCode
{
    class QueryCommand : ICommand
    {
        #region Fields
        private Action _execute;
        private Func _canExecute;
        #endregion 

        public QueryCommand(Action execute)
            : this(execute, null)
        {
        }
        public QueryCommand(Action execute, Func canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }

        #region ICommand Member

        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested += value;

                }
            }
            remove
            {
                if (_canExecute != null)
                {
                    CommandManager.RequerySuggested -= value;

                }
            }
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute();
        }

        public void Execute(object parameter)
        {
            _execute();
        }
        #endregion
    }
}

4、TableInfo实体

using System;
using System.Collections.Generic;
using System.Text;

namespace NEasyCode.Entity
{
    public class TableInfo
    {
        public string TableName { get; set; }
        public string TableDesc { get; set; }
        public int ColumnId { get; set; }
        public string ColumnName { get; set; }
        public bool ColumnIsPrimaryKey { get; set; }
        public bool ColumnIsIdentity { get; set; }
        public string ColumnType { get; set; }
        public int ColumnLength { get; set; }
        public int ColumnPrecision { get; set; }
        public int ColumnScale { get; set; }
        public bool ColumnIsNullAble { get; set; }
        public string ColumnDefaultValue { get; set; }
        public string ColumnDesc { get; set; }
        public string ColumnIndexName { get; set; }
        public string ColumnIndexSort { get; set; }
        public DateTime ColumnCreateDate { get; set; }
        public DateTime ColumnModifyDate { get; set; }
    }
}

5、运行效果

6、有几点问题,研究的不深,可能因为使用的不算完全纯正的mvvm的原因,有几点疑惑。

6.1 树控件数据源不需要调用RaisePropertyChanged,但是DataGrid需要,没有搞明白为什么这样。

6.2 树控件的绑定事件按网上的无法使用,.netCore下无法引入NuGet下的System.Windows.Interactivity,其它引入方式未试验,直接使用事件绑定的方式了。

通过Command绑定事件

在项目中引用 System.Windows.Interactivity.WPF(简单来说该插件可以将页面控件的Event转为ViewModel中的Command)
在窗体中添加引用
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
绑定Command到SelectedItemChanged事件


    
        
    

 

后续测试:在.net5 预览版下是可以的,.netCore下不行,

 

 7、在xp下无法运行,传家项目没有必须升级的需求还是用.net4.0吧。