温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何在c#中使用WPF对DataGrid中的Cell进行编辑

发布时间:2021-03-03 16:03:49 来源:亿速云 阅读:325 作者:Leah 栏目:开发技术

如何在c#中使用WPF对DataGrid中的Cell进行编辑?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

1 MainWindow

<Window x:Class="DataGridCellDoubleClickDemo.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:xceed="http://schemas.xceed.com/wpf/xaml/datagrid"         xmlns:models="clr-namespace:DataGridCellDoubleClickDemo.Models"         xmlns:views="clr-namespace:DataGridCellDoubleClickDemo.Views"         mc:Ignorable="d"         Title="DataGridDemo" Height="450" Width="800">     <Window.Resources>         <DataTemplate x:Key="CustomTemplate">             <Border BorderThickness="1" BorderBrush="Blue">                 <TextBlock Text="{Binding Path=Display }"  FontWeight="Bold"                            HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />             </Border>         </DataTemplate>         <DataTemplate x:Key="RowHeadTemplate" DataType="{x:Type models:RecipeControlVariable}">             <TextBlock Text="{Binding DisplayName}"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Foreground="Black" FontSize="12"/>         </DataTemplate>         <xceed:DataGridCollectionViewSource x:Key="recipeData" Source="{Binding RecipeVariables}"></xceed:DataGridCollectionViewSource>     </Window.Resources>     <Grid>         <xceed:DataGridControl x:Name="DataGridControl"                                AutoCreateColumns="False"                                FontSize="13"                                VerticalContentAlignment="Center"                                BorderBrush="Gray"                                BorderThickness="1"                                ItemsPrimaryAxis="Horizontal"                                PagingBehavior="LeftToRight"                                UpdateSourceTrigger="CellContentChanged"                                SelectionUnit="Cell"                                SelectionMode="Single"                                                              ItemsSource="{Binding  Source={StaticResource recipeData}}">             <xceed:DataGridControl.View>                 <xceed:TableflowView FixedColumnCount="1" ContainerHeight="30" x:Name="tblView"                                         VerticalGridLineThickness="0.5" HorizontalGridLineBrush="Gray"                                         HorizontalGridLineThickness="1" VerticalGridLineBrush="Black"                                         RowFadeInAnimationDuration="0"                                         ScrollingAnimationDuration="0" ColumnStretchMinWidth="10"                                         DetailIndicatorWidth="20" ShowRowSelectorPane="False"                                         ShowScrollTip="False" UseDefaultHeadersFooters="False">                     <xceed:TableflowView.FixedHeaders>                         <DataTemplate>                             <xceed:ColumnManagerRow AllowColumnReorder="False" AllowColumnResize="True" AllowDrop="False" AllowSort="False" />                         </DataTemplate>                     </xceed:TableflowView.FixedHeaders>                 </xceed:TableflowView>             </xceed:DataGridControl.View>               <xceed:DataGridControl.DefaultCellEditors>                 <xceed:CellEditor x:Key="{x:Type models:SmartCellViewModel}">                     <xceed:CellEditor.EditTemplate>                         <DataTemplate>                             <views:SmartCellEditor Content="{xceed:CellEditorBinding}"  VerticalAlignment="Center"                                                    Height="{Binding ActualHeight,RelativeSource={RelativeSource AncestorType={x:Type Border},AncestorLevel=1}}"></views:SmartCellEditor>                         </DataTemplate>                     </xceed:CellEditor.EditTemplate>                 </xceed:CellEditor>             </xceed:DataGridControl.DefaultCellEditors>           </xceed:DataGridControl>     </Grid> </Window>

  在View部分主要是通过引用Xceed中的DataGridControl控件进行扩展的,这个里面主要是需要设置DataGridControl的View和DefaultCellEditor这个里面DefaultCellEditor是本文的重点,这个就是单元格Cell双击后进行编辑的主体,在这个里面我们需要指定CellEditor的EditTemplate,这里面需要匹配一个DataTemplate,这个里面是一个SmartCellEditor的子View,下面我们来看看这个SmartCellEditor里面是什么内容?

  2 SmartCellEditor

<UserControl x:Class="DataGridCellDoubleClickDemo.Views.SmartCellEditor"              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"              xmlns:conv="clr-namespace:DataGridCellDoubleClickDemo.Converters"              xmlns:xceed="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"              mc:Ignorable="d"              d:DesignHeight="450" d:DesignWidth="800">     <UserControl.Resources>         <conv:VisibilityConverter x:Key="visConverter" />         <conv:TimeSpanConverter x:Key="timeSpanConverter" />         <conv:NumConverter x:Key="numConverter" />         <conv:BoolConverter x:Key="boolConverter" />     </UserControl.Resources>       <StackPanel Margin="0">         <!--TextBlock-->         <TextBlock x:Name="textBlock"                    Background="{Binding Background}"                    Foreground="{Binding Foreground}"                    Text="{Binding Path=Display,Mode=OneWay}"                     ToolTip="{Binding ToolTip}"                    FontWeight="{Binding FontWeight}"                    VerticalAlignment="Stretch"                     Visibility="{Binding Path=., Converter={StaticResource visConverter},ConverterParameter=TextBlock}"/>             <!--Editable ComboBox-->         <ComboBox x:Name="editableComboBox" ItemsSource="{Binding SmartCellData.Selections}" IsEditable="True"  VerticalAlignment="Stretch" VerticalContentAlignment="Center"                   DisplayMemberPath="SelectionDisplayName" Text="{Binding CellValue,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"                   Visibility="{Binding Path=., Converter={StaticResource visConverter},ConverterParameter=EditableComboBox}" />           <!--Readonly ComboBox-->         <ComboBox x:Name="readonlyComboBox"  VerticalAlignment="Center" VerticalContentAlignment="Stretch"  ItemsSource="{Binding SmartCellData.Selections}" IsEditable="False"                   DisplayMemberPath="SelectionDisplayName" SelectedValuePath="ControlName" SelectedValue="{Binding Path=CellValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"                   Visibility="{Binding Path=., Converter={StaticResource visConverter},ConverterParameter=ReadonlyComboBox}" />             <!--Text Input TextBox-->         <TextBox HorizontalContentAlignment="Left"  VerticalAlignment="Stretch" VerticalContentAlignment="Center" Text="{Binding CellValue}"                  Visibility="{Binding Path=., Converter={StaticResource visConverter},ConverterParameter=TextBox}" TextAlignment="Left" />             <!--Number Input TextBox-->         <xceed:DecimalUpDown HorizontalContentAlignment="Left"  VerticalAlignment="Stretch" VerticalContentAlignment="Center"  FormatString="G" Value="{Binding Path=CellValue,Converter={StaticResource numConverter},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"                              Increment="1" Visibility="{Binding Path=., Converter={StaticResource visConverter},ConverterParameter=DecimalUpDown}" TextAlignment="Left" />             <!--CheckBox-->         <CheckBox x:Name="checkBox"  VerticalAlignment="Stretch" VerticalContentAlignment="Center"  Content="{Binding Tag}" IsChecked="{Binding Path=CellValue,Converter={StaticResource boolConverter},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"                   Visibility="{Binding Path=., Converter={StaticResource visConverter},ConverterParameter=CheckBox}" />             <!--TimePicker-->         <xceed:DateTimeUpDown Format="Custom" FormatString="HH:mm:ss"  VerticalAlignment="Stretch" VerticalContentAlignment="Center"  Value="{Binding Path=CellValue,Converter={StaticResource timeSpanConverter},Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"                               Visibility="{Binding Path=., Converter={StaticResource visConverter},ConverterParameter=TimePicker}" CultureInfo="uk-UA" />       </StackPanel> </UserControl>

  在这个里面我们在一个StackPanel中放置了匹配各种数据类型的Template,并且每一个的Visibility都是由visConverter这个自定义的Converter来实现的,后面我们会分析这个Converter里面的内容,这些代码的整体思想就是每次这个StackPanel里面的Template都只有一个可以显示,其它的都是隐藏的,哪一个会显示是根据当前的数据类型决定的,每一个注释表示每一个类型的数据,比如我们如果定义的是Bool类型,那么当我们双击单元格Cell的时候会出现一个CheckBox供我们编辑,所以这个里面我们需要根据我们定义的数据类型来扩展对应的模板,当我们双击单元格的时候就会显示这个模板从而进行编辑数据。

  3 MainWindowViewModel

这个里面是定义的MainWindow对应的DataContext,在这里面我们会初始化绑定到MainWindow中DataGridControl的ItemsSource,我们先来看看这个里面核心的代码并就其中的要点进行分析。

using DataGridCellDoubleClickDemo.Models; using System; using System.Collections.ObjectModel; using System.Windows;   namespace DataGridCellDoubleClickDemo {     public class MainWindowViewModel : NotificationObject     {         public MainWindowViewModel(Xceed.Wpf.DataGrid.DataGridControl dataGridControl)         {             DataGridControl = dataGridControl;             InitRecipeVariables();         }             #region Properties         private ObservableCollection<RecipeControlVariable> _RecipeVariables = new ObservableCollection<RecipeControlVariable>();           public ObservableCollection<RecipeControlVariable> RecipeVariables         {             get { return _RecipeVariables; }             set             {                 if (value != _RecipeVariables)                 {                     _RecipeVariables = value;                     OnPropertyChanged(nameof(RecipeVariables));                 }               }         }           public Xceed.Wpf.DataGrid.DataGridControl DataGridControl { get; set; }           #endregion           #region Private Methods         private void InitRecipeVariables()         {             _RecipeVariables.Add(new RecipeControlVariable             {                 ControlName = "Name",                 DisplayName = "Name",                 StepValues = new ObservableCollection<SmartCellViewModel>                 {                     new SmartCellViewModel                     {                         CellValue="Step",                         ErrorInfo=null,                         SmartCellData=new RecipeVariableItem                         {                              ControlName = "Name",                              DisplayName = "Name",                              VariableEditorType=RecipeVariableEditorType.TextInput                         }                     },                     new SmartCellViewModel                     {                         CellValue="Step",                         ErrorInfo=null,                         SmartCellData=new RecipeVariableItem                         {                              ControlName = "Name",                              DisplayName = "Name",                              VariableEditorType=RecipeVariableEditorType.TextInput                         }                     }                 }               });             _RecipeVariables.Add(new RecipeControlVariable             {                 ControlName = "Time",                 DisplayName = "Process Time(Sec)",                 StepValues = new ObservableCollection<SmartCellViewModel>                 {                     new SmartCellViewModel                     {                         CellValue="0",                         ErrorInfo=null,                         SmartCellData=new RecipeVariableItem                         {                              ControlName = "Time",                              DisplayName = "Process Time(Sec)",                              VariableEditorType=RecipeVariableEditorType.NumInput                         }                     },                     new SmartCellViewModel                     {                         CellValue="0",                         ErrorInfo=null,                         SmartCellData=new RecipeVariableItem                         {                              ControlName = "Time",                              DisplayName = "Process Time(Sec)",                              VariableEditorType=RecipeVariableEditorType.NumInput                         }                     }                 }               });             _RecipeVariables.Add(new RecipeControlVariable             {                 ControlName = "FrontChemical",                 DisplayName = "FrontChemical",                 StepValues = new ObservableCollection<SmartCellViewModel>                 {                     new SmartCellViewModel                     {                         CellValue="None",                         ErrorInfo=null,                         SmartCellData=new RecipeVariableItem                         {                              ControlName = "FrontChemical",                              DisplayName = "FrontChemical",                              VariableEditorType=RecipeVariableEditorType.ReadOnlySelection,                              Selections=new ObservableCollection<SelectionItem>                              {                                  new SelectionItem                                  {                                      SelectionControlName="CHEM1",                                      SelectionDisplayName="CHEM1",                                  },                                  new SelectionItem                                  {                                      SelectionControlName="N2",                                      SelectionDisplayName="N2",                                  },                                  new SelectionItem                                  {                                      SelectionControlName="CDIW",                                      SelectionDisplayName="CDIW",                                  },                                  new SelectionItem                                  {                                      SelectionControlName="",                                      SelectionDisplayName="None",                                  }                              }                         }                     },                     new SmartCellViewModel                     {                         CellValue="None",                         ErrorInfo=null,                         SmartCellData=new RecipeVariableItem                         {                              ControlName = "FrontChemical",                              DisplayName = "FrontChemical",                              VariableEditorType=RecipeVariableEditorType.ReadOnlySelection,                              Selections=new ObservableCollection<SelectionItem>                              {                                  new SelectionItem                                  {                                      SelectionControlName="CHEM1",                                      SelectionDisplayName="CHEM1",                                  },                                  new SelectionItem                                  {                                      SelectionControlName="N2",                                      SelectionDisplayName="N2",                                  },                                  new SelectionItem                                  {                                      SelectionControlName="CDIW",                                      SelectionDisplayName="CDIW",                                  },                                  new SelectionItem                                  {                                      SelectionControlName="",                                      SelectionDisplayName="None",                                  }                              }                         }                     }                 }               });             _RecipeVariables.Add(new RecipeControlVariable             {                 ControlName = "NozzleBindingSetting",                 DisplayName = "Nozzle Scan",                 StepValues = new ObservableCollection<SmartCellViewModel>                 {                     new SmartCellViewModel                     {                         CellValue="Default",                         ErrorInfo=null,                         SmartCellData=new RecipeVariableItem                         {                              ControlName = "NozzleBindingSetting",                              DisplayName = "Nozzle Scan",                              VariableEditorType=RecipeVariableEditorType.TextInput                         }                     },                     new SmartCellViewModel                     {                         CellValue="Default",                         ErrorInfo=null,                         SmartCellData=new RecipeVariableItem                         {                              ControlName = "NozzleBindingSetting",                              DisplayName = "Nozzle Scan",                              VariableEditorType=RecipeVariableEditorType.TextInput                         }                     }                 }               });         }         #endregion           /// <summary>         /// reload datagrid content         /// </summary>         public void RefreshDataGrid()         {             try             {                 if (null == DataGridControl) return;                 //generate columns in Grid                 DataGridControl.CurrentColumn = null;                 if (DataGridControl.Columns.Count > 0)                     DataGridControl.Columns.Clear();                   var template = (DataTemplate)this.DataGridControl.FindResource("CustomTemplate");                 var rowTemplate = (DataTemplate)this.DataGridControl.FindResource("RowHeadTemplate");                   DataGridControl.Columns.Add(new Xceed.Wpf.DataGrid.Column()                 {                     Width = 140,                     Title = "Name",                     FieldName = ".",                     CellContentTemplate = rowTemplate                 });                   var cellEditor = DataGridControl.DefaultCellEditors[typeof(SmartCellViewModel)];                   for (int index = 0; index < RecipeVariables[0].StepValues.Count; index++)                 {                     int width = 1;                     for (int n = 0; n < RecipeVariables.Count; n++)                     {                         string display = RecipeVariables[n].StepValues[index].Display;                         if (!string.IsNullOrWhiteSpace(display))                         {                             int temp = display.Length * 7;                             width = Math.Max(temp, width);                         }                     }                     width = (int)(width * 1.1);                     width = Math.Max(width, 80);                     DataGridControl.Columns.Add(new Xceed.Wpf.DataGrid.Column()                     {                           Title = string.Format("Step {0}", index + 1),                         FieldName = string.Format("StepValues[{0}]", index),                         CellContentTemplate = template,                         AllowSort = false,                         Width = width,                         MaxWidth = width * 2,                         CellEditor = cellEditor                     });                 }               }             catch (Exception ex)             {               }

  在这个里面我们重点分析下RefreshDataGrid这个子函数,在我们的MainWindowViewModel中我们定义的RecipeVariables是最终绑定到MainWindow中定义的DataGridControl中的ItemsSource,是整个控件的数据源,由于我们这个DataGird的第一列和后面的Step列数据类型不同,所以我们的RefreshDataGrid函数中增加Column列的时候是分作两个部分,第一个部分是单独增加一列,后面的列是通过循环StepValues这个集合来动态进行增加的,代码中我们定义了多少个StepValue,那么后面就会有多少列,这个里面的重点是增加Column的时候FieldName的赋值,这个是十分关键的,这个关系到能够让每一列获取到正确的数据源,例如第一列赋值Filed= “.” 表示直接从当前绑定的数据源获取数据,另外后面的Step列的每一个FieldName是动态进行赋值的,赋值语句是:FieldName = string.Format("StepValues[{0}]", index),这个里面Index是一个动态值,这个是非常关键的一步,另外后面的Step列由于需要通过双击进行编辑所以每一个Column是需要赋值CellEditor对象的,另外这个ViewModel中的DataGridControl是通过构造函数进行赋值的,构造函数中的赋值就是MainWindow中定义的DataGridControl对象,这个在阅读代码时需要特别注意。

  4 Models

Models主要是定义的数据集合,我们的代码中主要包括RecipeControlVariable和SmartViewModel这两个部分,这两个部分分别对应DataGridControl的数据源以及双击进行编辑的SmartCellEditor两个部分一一对应。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI