当前位置:必发365电子游戏 > 编程 > 【MVVM Dev】DataColumn中的TextBox与ComboBox的并存
【MVVM Dev】DataColumn中的TextBox与ComboBox的并存
2019-12-19

一、前言

     在WPF编程中,有的时候候大家应用DataGrid会须求在四个DataColumn中既有TextBox,也要有ComboBox或然TextBlock等其余数据彰显样式。

       这时我们就供给DataGridTemplateColumn去自定义大家的Column样式,通过数据类型去剖断该消息是以Text博克斯展现依旧以ComboBox来显示。

图片 1

 

 

二、从数据库出发

     所谓兵马未到,未雨筹划。数据库的字段应该醒目告知大家该条数据是哪位数据类型?是字符串型照旧多选型?是或不是可编写制定?

       这一个清晰的音信都能为大家随后的MVVM绑定端来宏大的低价。

       数据库的字段能够差不离如此:

       1. ID

       2. Keyword

       3. Name

       4. Value

       5. ItemsValue (用来告诉有怎么着选用途卡塔尔国

       6. DataType (是字符串型,还是多选型,依然其余?卡塔尔国

       7. IsAcceptInput (展现在分界面上后是还是不是可编写制定卡塔尔国

       范例:

图片 2

      大家可以从上表看出,第1与第2条数据应该是TextBox展现,而第3与第4条则是ComboBox展现。

 

三、在代码中策动好相应的枚举

      当大家打算完数据库的多少时,在代码中我们会用Dapper, EF, Nhibernate等等将数据库字段映射为相应的数据类型:

public Class ExampleInfoData
{

   public long Id {get;set;}

   public string Keyword {get;set;}

   public string PropertyName {get;set;}

   public DataItem PropertyValue {get;set;}

   public List<DataItem> ItemValues {get;set;}

   public int DataType {get;set;}

   public bool IsAcceptInput {get;set;}

}

      

      这里我们看来有个类叫 DataItem, 这是为了什么啊?大家看下表率:

public class DataItem
{
        public string DisplayName { get; set; }  //显示值   用来在界面上显示用的
        public string ItemValue { get; set; }    //原始值

        //这个方法是为了能让界面正常显示从数据库读取的值,不用这个方法的话就算数据库中存有默认值,绑定之后它也不会正常显示在界面上
        public override bool Equals(object obj)  
        {
            if (!(obj is DataItem))
            {
                return false;
            }
            DataItem di = obj as DataItem;
            return di != null && di.ItemValue == ItemValue;
        }

        public override int GetHashCode()      //配合Equals方法,两者一起使用
        {
            return ItemValue.GetHashCode();
        }
}

 

      对于多选型的数目,大家也应该策画好相应的枚举值,有了Description能方便的给前边的DisplayName提供值。

public enum ProjectType
{
    [Description("类型一")]
    T_1 = 0,

    [Description("类型二")]
    T_2 = 1,

     [Description("类型三")]
    T_3 = 2,
}


public enum MemberType
{
    [Description("成员类型一")]
    M_1 = 0,

    [Description("成员类型二")]
    M_2 = 1,

     [Description("成员类型三")]
    M_3 = 2,
}

 

四、ViewModel的准备

        打算好上述专业,大家将在初叶运用MVVM了,首先要把ViewModel的数目填充上,这里作者一无所知写代码,看清套路就会自身开车了。

  using System.Collections.Generic;
  using System.Collections.ObjectModel;
  using System.Linq;
  using DevExpress.Mvvm;

  namespace Example
  {
      public class ProjectSettingViewModel : ViewModelBase
     {
         public ObservableCollection<ExampleInfoData> ProjectInfo { get; set; } 

         public New_ProjectSettingViewModel()
         {
              ProjectInfo = new ObservableCollection<ExampleInfoData>(FillProjectInfo());            
         }


        public List<ExampleInfoData> FillProjectInfo()
        {
             List<ExampleInfoData> projectSettingInfoList = new List<ExampleInfoData>();
             var dB_projectSettingInfo = projectSettingDB.GetAll(); //get Data From DB
             foreach (var item in dB_projectSettingInfo)
             {             
                 ExampleInfoData projectSettingInfo = new ExampleInfoData ();
                 projectSettingInfo.Id = item.Id;
                 projectSettingInfo.KeyWord = item.Keyword;
                 projectSettingInfo.PropertyName = item.Name;
                 projectSettingInfo.TabId = item.TabId;
                 projectSettingInfo.DataType = item.DataType;
                 projectSettingInfo.AcceptInput = item.AcceptInput;
                 if (item.ItemValues == null)
                 {
                     DataItem smText = new DataItem();
                     smText.DisplayName = smText.ItemValue = item.Value;
                     projectSettingInfo.ProjectSettingValue = smText;
                     projectSettingInfo.ItemValues = null;
                 }
                 else
                 {
                     DataItem smCombox = new DataItem();
                     smCombox.ItemValue = item.Value;
                     smCombox.DisplayName = JudgeType(item.Value);  // 这个函数判断是哪种枚举类型的!!!并返回相应的Description
                     projectSettingInfo.ProjectSettingValue = smCombox;

                     projectSettingInfo.ItemValues = new List<DataItem>();
                     foreach (var iv in item.ItemValues.Split(','))
                     {
                         DataItem sm = new DataItem();
                         sm.ItemValue = iv;
                         sm.DisplayName = JudgeType(iv);
                         projectSettingInfo.ItemValues.Add(sm);
                     }
                 }
                 projectSettingInfoList.Add(projectSettingInfo);
             }
             return projectSettingInfoList;
        } 


        public string JudgeType(string strValue)
        {
            if (!string.IsNullOrEmpty(strValue))
            {
                string strType = strValue.Split('_')[0];
                if (string.Equals(strType, "T", StringComparison.CurrentCultureIgnoreCase))
                {
                    return GetDescriptionFromEnumValue((ProjectType)Enum.Parse(typeof(ProjectType), strValue)); //获取Description的方法各位自己写
                }
                else if (string.Equals(strType, "M", StringComparison.CurrentCultureIgnoreCase))
                {
                    return GetDescriptionFromEnumValue((MemberType)Enum.Parse(typeof(MemberType), strValue));
                }
                else
                {
                    return null;
                }
            }
            return null;
        }
    }
 }

 

五、View的准备

<UserControl x:Class="Example"
             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"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="../../Controls/ProjectSettingDataGrid.xaml"/>  !!!Here
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

    <Grid Margin="0,15,0,0">
              <DataGrid x:Name="dgPJInfo"  
                 CanUserSortColumns="False"
                 AutoGenerateColumns="False"
                 CanUserAddRows="False"
                 CanUserReorderColumns="False"
                 AlternatingRowBackground="#EBEBEB" 
                 Background="White"
                 ItemsSource ="{Binding ProjectInfo}">
                <DataGrid.Columns>
                    <DataGridTextColumn Width=".4*" IsReadOnly="True" Header="属性名称" FontSize="15"  Binding="{Binding PropertyName}"></DataGridTextColumn>
                    <DataGridTemplateColumn Width=".4*" Header="属性值" CellTemplateSelector="{StaticResource DataGridTemplateSelector}"></DataGridTemplateColumn>  !!!Here
                </DataGrid.Columns>
            </DataGrid>
     </Grid>
</UserControl>

       

         上边那些View告诉大家那么些DataGridTemplateColumnCellTemplateSelector

         绑定到<ResourceDictionary Source="../../Controls/ProjectSettingDataGrid.xaml"/>里的DataGridTemplateSelector

         那么ProjectSettingDataGrid.xaml该怎么写吗?

 

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:controls="clr-namespace:Example.Controls"
             xmlns:view="clr-namespace:Example.UI.View">


    <DataTemplate x:Key="TextBoxTemplate">  //TextBox的Template
        <TextBox Text="{Binding PropertyValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" FontSize="15"/>
    </DataTemplate>

    <DataTemplate x:Key="TextBlockTemplate">  //TextBlock的Template
        <TextBlock Text="{Binding PropertyValue}" FontSize="15"/>
    </DataTemplate>

    <DataTemplate x:Key="ComboBoxTemplate">  //Combobox的Template
        <ComboBox ItemsSource="{Binding ItemValues}" FontSize="15" IsEditable="{Binding IsAcceptInput}" 
        SelectedItem="{Binding PropertyValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="DisplayName"/> !!!注意这里的DisplayMemberPath !!!
    </DataTemplate>

    <controls:DataGridTemplateSelector x:Key="DataGridTemplateSelector" 
                                      TextBoxDataTemplate="{StaticResource TextBoxTemplate}" 
                                      TextBlockDataTemplate="{StaticResource TextBlockTemplate}" 
                                      ComboBoxDataTemplate="{StaticResource ComboBoxTemplate}"/>
</ResourceDictionary>

        

         那下好了,定义好了各样Template,笔者剩下的事便是基于数据,判定选用哪类Template,

        ProjectSettingDataGrid.xaml.cs能够如此写:

using System;
using System.Windows;
using System.Windows.Controls;
using Example.ProjectSetting;


namespace Example.Controls
{

    public partial class PropertyDataGrid : DataGrid
    {
        public PropertyDataGrid()
        {

        }
    }

    public class DataGridTemplateSelector : DataTemplateSelector
    {
        public DataTemplate TextBoxDataTemplate { get; set; }
        public DataTemplate TextBlockDataTemplate { get; set; }
        public DataTemplate ComboBoxDataTemplate { get; set; }

        public override DataTemplate SelectTemplate(object item, DependencyObject container) //这里的object item传进来的就是ViewModel中ProjectInfo的一条条数据!!!
        {
            if (null == item)
            {
                return null;
            }
            if (item is ExampleInfoData)
            {
                ExampleInfoData projectInfo = item as ExampleInfo;
                if (projectInfo.DataType == (int) ((DataEnum) Enum.Parse(typeof (DataEnum), "DATA_ENUM")))  !!!注意这里,在数据库定义的DataType此时就起到了判断Template的作用!!!
                {
                    return ComboBoxDataTemplate;
                }
                else
                {
                    return TextBoxDataTemplate;
                }
            }

            // else if (item is OtherInfoData)
            // {
            //        //do something
            // }

            else
            {
                return null;
            }           
        }
    }
}

 

【MVVM Dev】DataColumn中的TextBox与ComboBox的并存。六、总结

      如上内容正是独具的覆辙,

       同理可得正是:

       1. 数据库字段

       2. 映射字段

       3. 枚举类对应 

       4. ViewModel 数据填充 

       5. DataGridTemplateColumn的绑定

       6. 定义各样Template并作出剖断接受哪一种Template