IsReadOnly常用数据输入控件介绍
TextBox控件
CheckBox控件
RadioButton控件
ComboBox控件
示例:比如CombBox控件要绑定到model实体上,model实体有ID,Name两个属性,设置方法如下
<ComboBox ItemsSource="{StaticResource modelsResource}" SelectedValuePath="ID" SelectedValue="{Binding ModelID, Mode=TwoWay}" DisplayMemberPath="Name" />
其中SelectedValuePath是ComboBox返回的值,而SelectedValue是ComboBox返回值的绑定位置(Product实体的ModelID属性),而DisplayMemberPath是ComboBox在视图中显示的值;
另外ComboBox控件还有一个SelectedItem属性,该属性返回选定的Model对象,很少使用。
需要注意:显示 在ComboBox的集合项目应该在绑定SelectedItem/SelectedValue属性之前进行填充,否则将不会显示选定的项目。也就是说,需要先从服务器加载需要填充的集合内容,数据加载的顺序相当重要。
ComboBox也可以定制显示效果,使用ItemTemplate属性进行设置。
ListBox控件:前已述及;
Calendar控件
DatePicker控件
该控件可以让出显示区域,除了Calendar控件已有的属性以外还添加了一个SelectDateFormat属性,可以定制在文本框中显示的日期样式;
TimeUpDown控件(属于Silverlight ToolKit,应引用System.Windows.Controls.Data.Toolkit.dll程序集)
使用该控件只能输入正确的时间,例如不能输入9:80这样的数据;
The TimePicker控件(属于Silverlight ToolKit,应引用System.Windows.Controls.Data.Toolkit.dll程序集)
可以使用PopupMinutesInterval属性对间隔时间进行设置(单位为分钟);
NumericUpDown(属于Silverlight ToolKit,应引用System.Windows.Controls.Data.Toolkit.dll程序集)
<toolkit:NumericUpDown DecimalPlaces="2" Increment="0.5" Value="{Binding ListPrice, Mode=TwoWay}" />
DomainUpDown控件(属于Silverlight ToolKit,应引用System.Windows.Controls.Data.Toolkit.dll程序集)
有点像ComboBox控件,但是在右侧有上下选择按钮
<toolkit:DomainUpDown ItemsSource="{StaticResource StatesResource}" />
因为该控件并没有DisplayMeberPath,SelectedValuePath和SelectedValue属性,因此通过只用于显示简单类型数组,如文本,数字等;
AutoCompleteBox 控件(属于Silverlight ToolKit,应引用System.Windows.Controls.Data.Toolkit.dll程序集)
AutoCompleteBox 控件可以实现类似百度搜索提示的效果,如图所示:
实现此功能只需要将ItemsSource属性绑定到字符串集合即可。
<sdk:AutoCompleteBox ItemsSource="{StaticResource StatesResource}" />
Lable控件
使用Lable控件主要是显示相关字段的简介,相比TextBlock控件,其Targe属性具有特殊功能:当关联控件验证失败,Lable控件显示为红色指示输入错误;当关联控件拽定为必填,则显示粗体:
<sdk:Label Content="Name:" Target="{Binding ElementName=ProductNameTextBox}" />
检测数据是否发生更改:“Dirty”
bool hasChanges = ((Entity)ProductsDataForm.CurrentItem).HasChanges;
DataGrid控件作为编辑控件
DataGrid控件作为编辑控件还是有很多应用场景的,比如需要向订单中录入多款产品,包括型号,数量,价格等,这时候使用前面介绍的表单显然不够方便:
1、配置列:使用前面的提到的三种模板类型,可以将列配置为任意样式的控件,便于进行数据录入;
2、添加行:Silverlight中的DataGrid控件并没有AddRow或DeleteRow方法可用,因此需要使用变通的方法来实现行的添加:
最简单的方法是在视图上添加一个按钮,点击按钮后就在绑定的数据集合上添加一个新项,相应地DataGrid控件就同步添加了一行,如果使用集合视图,直接调用集合的ADD方法即可;如果使用DDS控件,则需要将ItemsSource属性强制转换为DomainDataSourceView:
DomainDataSourceView view = productDataGrid.ItemsSource as DomainDataSourceView; Product newProduct = new Product(); view.Add(newProduct);
一旦添加了新行,需要设置新行为输入焦点,设置为编辑模式:
// 焦点调整到新增行的第一个单元格并开始编辑
productDataGrid.Focus();
productDataGrid.SelectedItem = newProduct;
productDataGrid.CurrentColumn = productDataGrid.Columns[0];
productDataGrid.ScrollIntoView(productDataGrid.SelectedItem,
productDataGrid.CurrentColumn);
productDataGrid.BeginEdit();
有个小问题,如果某个字段要求不能为空,在新增行会提示不能通过验证,用户体验不太好,解决的唯一办法就是给新增的行赋初始值。
插入行
向DataGrid控件中插入行与添加行差不多,需要调用Insert方法:
ObservableCollection<Product> collection = productDataGrid.ItemsSource as ObservableCollection<Product>; int insertIndex = productDataGrid.SelectedIndex + 1; //当DataGrid首行被选定时会遇到一些奇怪的行为 insertIndex = 1; collection.Insert(insertIndex, new Product()); // 选择并滚动到新添加行的的第一个单元格,并开始编辑 productDataGrid.SelectedIndex = insertIndex; productDataGrid.CurrentColumn = productDataGrid.Columns[0]; productDataGrid.ScrollIntoView(productDataGrid.SelectedItem, productDataGrid.CurrentColumn); productDataGrid.BeginEdit();
始终维持空行以输入新记录
1)设置一个变量作为新项目列表对象:
private object addRowBoundItem = null;
2)向已绑定的集合中添加新对象,将新对象败给全局变量:
//下述代码是绑定到DDS的情形 DomainDataSourceView view = productDataGrid.ItemsSource as DomainDataSourceView; addRowBoundItem = new Product(); view.Add(addRowBoundItem);
3)处理DataGrid的RowEditEnded事件:
private void productDataGrid_RowEditEnded(object sender, DataGridRowEditEndedEventArgs e) { if (e.EditAction == DataGridEditAction.Commit) { if (e.Row.DataContext == addRowBoundItem) { DomainDataSourceView view = productDataGrid.ItemsSource as DomainDataSourceView; addRowBoundItem = new Product(); view.Add(addRowBoundItem); productDataGrid.SelectedItem = addRowBoundItem; productDataGrid.CurrentColumn = productDataGrid.Columns[0]; productDataGrid.ScrollIntoView(addRowBoundItem, productDataGrid.CurrentColumn); productDataGrid.BeginEdit(); } } }
4)在提交变更到数据库之前,删除集合中的最后一项:
DomainDataSourceView view = productDataGrid.ItemsSource as DomainDataSourceView;
view.Remove(addRowBoundItem);
删除选定行
ObservableCollection<Product> collection = productDataGrid.ItemsSource as ObservableCollection<Product>; //将SelectedItems属性转换为集合类型以便可以使用Linq语法处理ce to be declared var removeItems = productDataGrid.SelectedItems.Cast<Product>().ToArray(); foreach (Product product in removeItems) collection.Remove(product);
为每行添加一个删除按钮
<sdk:DataGridTemplateColumn Width="80"> <sdk:DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Content="Delete" Click="DeleteButton_Click" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellTemplate> </sdk:DataGridTemplateColumn>
按钮的单击事件:
private void DeleteButton_Click(object sender, RoutedEventArgs e) { DomainDataSourceView view = productDataGrid.ItemsSource as DomainDataSourceView; view.Remove(((FrameworkElement)sender).DataContext); }
下拉列表列实现
<sdk:DataGridTemplateColumn x:Name="classColumn" Header="Class" Width="100"> <sdk:DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding Source={StaticResource productClasses}}" DisplayMemberPath="Name" SelectedValuePath="ID" SelectedValue="{Binding Class, Mode=TwoWay}" /> </DataTemplate> </sdk:DataGridTemplateColumn.CellEditingTemplate> </sdk:DataGridTemplateColumn>
关于List<T>
List<T>(T未实现INotifyPropertyChanged接口),适用于一次性绑定,适用于重新实例化整个List集合的绑定;
List<T>(T实现INotifyPropertyChanged接口),适用于修改集合中单笔数据的成员(比如说Student的Score属性);
ObservableCollection<T>(T未实现INotifyPropertyChanged接口),适用于增删集合中的数据(上面的Add和Remove按钮)。但是对于单笔数据的更改,是无能为力的。
使用ObservableCollection<T>,并且T实现了INotifyPropertyChanged接口。适用于上述三种情况,但最消耗资源.