关于使用MVVM模式在WPF的DataGrid控件中实现ComboBox编辑列
最近在做一个组态软件的项目,有一个需求需要在建立IO设备变量的时候选择变量的类型等。
建立IO变量的界面是一个DataGrid实现的,可以一行一行的新建变量,如下如所示:
这里需要使用带有ComboBox控件的列,如何实现呢?
我首先想到的是使用DataGridComboBoxColumn来实现,可是在绑定数据的时候出现了问题,数据怎么也绑定不上。后来经过多方查证,发现原来DataGridComboBoxColumn对数据源有限制,只能是一下3中情况之一:
1、静态资源。
2、x:静态代码实体。
3、ComboBoxItem类型的内联集合。
基于扩展性、代码规范等情况考虑,这三种方案都被否决了。
然后就想到使用DataGridTemplateColumn来实现。
xaml代码:
<DataGrid ItemsSource="{Binding Model.IoVariables}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTemplateColumn Header="类型"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding VariableType}"></TextBlock> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox SelectedItem="{Binding VariableType}" ItemsSource="{Binding DataContext.Model.VariableTypes,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"></ComboBox> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> <DataGridTextColumn Header="变量名" Binding="{Binding VariableName}"></DataGridTextColumn> </DataGrid.Columns> </DataGrid>
这里需要注意的一点是ComboBox的ItemsSource的绑定方式,在《关于WPF中ItemsControl系列控件中Item不能继承父级的DataContext的解决办法》一文中解释了这种绑定方式。
ViewModel代码:
using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using WpfApplication1.Models; namespace WpfApplication1.ViewModels { public class IOVariableViewModel : ViewModelBase { public IOVariableModel Model { get; set; } public IOVariableViewModel() { Model = new IOVariableModel(); Model.TestCommand = new RelayCommand(TestCommandHandler); Model.VariableTypes.Add("整型"); Model.VariableTypes.Add("实型"); Model.VariableTypes.Add("字符串"); } }
Model代码
using System.Collections.ObjectModel; using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; namespace WpfApplication1.Models { public class IOVariableModel : ViewModelBase { private ObservableCollection<IOVariable> _ioVariables; public ObservableCollection<IOVariable> IoVariables { get { return _ioVariables; } set { _ioVariables = value; RaisePropertyChanged(() => IoVariables); } } private ObservableCollection<string> _variableTypes; public ObservableCollection<string> VariableTypes { get { return _variableTypes; } set { _variableTypes = value; RaisePropertyChanged(() => VariableTypes); } } public RelayCommand TestCommand { get; set; } public IOVariableModel() { VariableTypes = new ObservableCollection<string>(); IoVariables = new ObservableCollection<IOVariable>(); } } }
IOVariable.cs的代码
namespace WpfApplication1.Models { public class IOVariable { public string VariableType { get; set; } public string VariableName { get; set; } } }
关于本文的源码:点击下载