程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 【MVVM DEV】DataColumn中的TextBox與ComboBox的並存,mvvmdatacolumn

【MVVM DEV】DataColumn中的TextBox與ComboBox的並存,mvvmdatacolumn

編輯:關於.NET

【MVVM DEV】DataColumn中的TextBox與ComboBox的並存,mvvmdatacolumn


一、前言

      在WPF編程中,有時候我們使用DataGrid會需要在一個DataColumn中既有TextBox,也要有ComboBox或者TextBlock等其他數據顯示樣式。

       這個時候我們就需要DataGridTemplateColumn去自定義我們的Column樣式,通過數據類型去判斷該信息是以TextBox顯示還是以ComboBox來顯示。

 

        PS:初入WPF-MVVM模式編程的童鞋可以先了解一下what is MVVM

 

二、從數據庫出發

      所謂兵馬未到,糧草先行。數據庫的字段應該明確告訴我們該條數據是哪個數據類型?是字符串型還是多選型?是否可編輯?

       這些清晰的信息都能為我們之後的MVVM綁定帶來極大的便利。

       數據庫的字段可以大致這樣:

       1. ID

       2. Keyword

       3. Name

       4. Value

       5. ItemsValue (用來告知有哪些選擇項)

       6. DataType (是字符串型,還是多選型,還是其他?)

       7. IsAcceptInput (顯示在界面上後是否可編輯)

       范例:

      我們可以從上表看出,第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; } } } }

 

六、總結

      以上內容就是所有的套路,

       簡單的說就是:

       1. 數據庫字段

       2. 映射字段

       3. 枚舉類對應 

       4. ViewModel 數據填充 

       5. DataGridTemplateColumn的綁定

       6. 定義各種Template並作出判斷選擇哪種Template

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved