这是我尝试使用Telerik GridView控件的具体示例。假设我有一个应用程序将读取带有n列的分隔文件(比如CSV)。值n可以在文件到文件之间变化,但在文件中是恒定的。应用程序以空网格开始,并根据需要添加列以匹配输入文件。网格将所有数据显示为所有单元格中的字符串。这适用于绑定到BindingList或将记录(对象)放入GridView.Items列表。
现在,我想要做的是在网格顶部放置一行(不会滚动的行),其中包含组合框。也就是说,在每列的顶部,第一行包含组合框。在第一次传递时,组合框只是一个下拉列表,但在下一个传递中,我将添加另一行,其中包含一组可编辑的组合框。现在,我们只考虑下拉列表。
我遇到的具体问题是我没有看到如何为特定单元格设置特定类型的控件。 Telerik提供了一个GridViewComboBoxColumn类,它将定义整个列的行为,但这不是我需要的。
由于列数可变,我认为代码隐藏将成为实现这种魔力的地方。我可能不得不在xaml中做一些事情但是,因为我只在WPF工作了几个月,所以没有什么东西可以跳出来。
我已经使用DataGridView和XtraGrid完成了类似的操作,但是这个让我很难过。指针将非常感激。
为了回应Jonathan D的回答,我已经提供了所提供的代码并对其进行了修改以识别第0行中的单元格何时被编辑。在这种情况下,当用户启动编辑操作时会显示一个下拉列表。
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace LLamasoft.DataGuru.Plugin.Internal.ConfigurationUI
{
public class RadGridViewComboboxHeaderColumn : GridViewBoundColumnBase
{
public static readonly DependencyProperty SelectedStringProperty =
DependencyProperty.Register("SelectedString", typeof(string), typeof(RadGridViewComboboxHeaderColumn), new PropertyMetadata(null));
public string SelectedString
{
get { return (string) GetValue(SelectedStringProperty); }
set { SetValue(SelectedStringProperty, value); }
}
public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)
{
// we need the row on which this cell lives
GridViewDataControl gridViewDataControl = cell.ParentRow.GridViewDataControl;
object currentEditItem = gridViewDataControl.Items.CurrentEditItem;
int index = gridViewDataControl.Items.IndexOf(currentEditItem);
FrameworkElement frameworkElement = null;
if (index == 0)
{
BindingTarget = ComboBox.SelectedValueProperty;
ComboBox comboBox = new ComboBox();
// seed some values,
// this list should be set right after construction if static, otherwise via callback if dynamic
comboBox.Items.Add(string.Empty);
comboBox.Items.Add("apples");
comboBox.Items.Add("oranges");
if (!comboBox.Items.Contains(cell.Value))
{
comboBox.Items.Add(cell.Value);
}
comboBox.SelectedValue = SelectedString;
frameworkElement = comboBox;
}
else
{
BindingTarget = TextBox.TextProperty;
TextBox textBox = new TextBox();
textBox.Text = SelectedString;
frameworkElement = textBox;
}
frameworkElement.SetBinding(BindingTarget, CreateValueBinding());
return frameworkElement;
}
public override object GetNewValueFromEditor(object editor)
{
// ensure that the control will return the correct value when queried for it
ComboBox comboBox = editor as ComboBox;
if (comboBox != null)
{
// bound to comboBox.SelectedValue which carries the correct value
}
TextBox textBox = editor as TextBox;
if (textBox != null)
{
// bound to textBox.Text which carries the correct value
}
return base.GetNewValueFromEditor(editor);
}
private Binding CreateValueBinding()
{
Binding valueBinding = new Binding();
valueBinding.Mode = BindingMode.TwoWay;
valueBinding.NotifyOnValidationError = true;
valueBinding.ValidatesOnExceptions = true;
valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
valueBinding.Path = new PropertyPath(this.DataMemberBinding.Path.Path);
return valueBinding;
}
}
}
好消息是,这表明任何编辑控件都可以根据需要在任何单元格中使用。
坏的部分是:1)必须在第0个列表位置插入虚拟记录,并且必须在那里保留,2)数据被存储回第0个记录的字段,并且可能需要不同的数据类型与其他记录中的等效字段相比,3)组合框仅在单元格处于编辑模式时显示。
对我来说,后一个问题在其他地方可能不是问题。我想要一个视觉提示,用户应该与列顶部的单元格进行交互。使用此方法,在编辑操作开始之前,顶行和其余行之间没有区别因素。我理想的解决方案是让细胞始终显示出它们的组合框。
我发现很难相信我面临的另一个问题是我无法轻易地锁定/冻结最顶行。我希望这条线在滚动后始终保持在顶部。没有_grid.Rows [0] .IsPinned = true功能。
Telerik已回应我的信息请求,并建议我使用模板选择器来确定单元格的表示方式。 (http://www.telerik.com/community/forums/wpf/gridview/need-just-first-row-in-grid-to-be-all-comboboxes.aspx#1820310)。此时,我将注意力转向测试该方法。
答案 0 :(得分:0)
您想要创建自己的列
using System.Windows;
using System.Windows.Data;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using System;
namespace Inspect
{
public class DateTimePickerColumn : GridViewBoundColumnBase
{
public TimeSpan TimeInterval
{
get
{
return (TimeSpan) GetValue(TimeIntervalProperty);
}
set
{
SetValue(TimeIntervalProperty, value);
}
}
public static readonly DependencyProperty TimeIntervalProperty =
DependencyProperty.Register("TimeInterval", typeof(TimeSpan), typeof(DateTimePickerColumn), new PropertyMetadata(TimeSpan.FromHours(1d)));
public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)
{
this.BindingTarget = RadDateTimePicker.SelectedValueProperty;
RadDateTimePicker picker = new RadDateTimePicker();
picker.IsTooltipEnabled = false;
picker.TimeInterval = this.TimeInterval;
picker.SetBinding(this.BindingTarget, this.CreateValueBinding());
return picker;
}
public override object GetNewValueFromEditor(object editor)
{
RadDateTimePicker picker = editor as RadDateTimePicker;
if (picker != null)
{
picker.DateTimeText = picker.CurrentDateTimeText;
}
return base.GetNewValueFromEditor(editor);
}
private Binding CreateValueBinding()
{
Binding valueBinding = new Binding();
valueBinding.Mode = BindingMode.TwoWay;
valueBinding.NotifyOnValidationError = true;
valueBinding.ValidatesOnExceptions = true;
valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
valueBinding.Path = new PropertyPath(this.DataMemberBinding.Path.Path);
return valueBinding;
}
}
}
这就是您创建自定义列的方式。如果您修改CreateCellEditElement方法,它将允许您按照自己喜欢的方式创建自定义单元格。您甚至应该能够检测到行号