我有一个Winforms应用程序。有两个班。一个班级存储有助于书籍的人。另一个类是可能的贡献类型列表(如编辑器,审阅者等)。
BookContributors 类是我的datagridview的数据源,并且工作得很好。现在,我想让 BookContributorTypes 类成为为 BookContributors 类提供信息的组合框。
到目前为止,在我的阅读中,看起来我有很多选项,包括使用类属性强制组合框进入datagridview,在类之间创建一对多的关系。
由于我的代码会有很多这类情况,我想这样做。我认为这意味着以某种方式显示两个类之间的关系,因此datagridview知道只显示组合框,但我不知道如何去做这个。
BookContributors由填写贡献者的人填充。例: BookContributor =“John Smith”; BookContributorFileAs =“史密斯,约翰”; BookContributorType =“rev”。
public class BookContributors : INotifyPropertyChanged
{
private string _bookContributor;
[DescriptionLocalized(typeof(ResourcesClassBooks), "BookContributorComment")]
[DisplayNameLocalized(typeof(ResourcesClassBooks), "BookContributorDisplayName")]
public string BookContributor
{
get { return _bookContributor; }
set
{
if (SetField(ref _bookContributor, value, "BookContributor"))
{
// When the user types an author name, add the sorted name to the sorted field.
// ex Name = William E Raymond
// ex File As = Raymond, William E
var name = _bookContributor.Split(' ');
if (name.Length >= 2)
{
string fileAsName = (name[name.Length - 1] + ",");
for (int i = 0; i <= (name.Length - 2); i++)
{
fileAsName = fileAsName + " " + name[i];
}
BookContributorFileAs = fileAsName;
}
}
}
}
private string _bookContributorFileAs;
[DescriptionLocalized(typeof(ResourcesClassBooks), "BookContributorFileAsComment")]
[DisplayNameLocalized(typeof(ResourcesClassBooks), "BookContributorFileAsDisplayName")]
public string BookContributorFileAs { get { return _bookContributorFileAs; } set { SetField(ref _bookContributorFileAs, value, "BookContributorFileAs"); } }
private string _bookContributorType;
[DescriptionLocalized(typeof(ResourcesClassBooks), "BookContributorTypeComment")]
[DisplayNameLocalized(typeof(ResourcesClassBooks), "BookContributorTypeDisplayName")]
public string BookContributorType { get { return _bookContributorType; } set { SetField(ref _bookContributorType, value, "BookContributorType"); } }
#region handle property changes
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetField<T>(ref T field, T value, string propertyName)
{
//if the value did not change, do nothing.
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
//the value did change, so make the modification.
field = value;
return true;
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
BookContributorTypes(填充XML文件中的bookContributor类型列表)。示例书籍贡献者类型ID:“rev”,“edt”。示例书籍贡献者类型描述:“审稿人”,“编辑”。
class BookContributorTypes : INotifyPropertyChanged
{
private string _bookContributorTypeId;
[DescriptionLocalized(typeof(ResourcesClassBooks), "BookContributorTypeIdComment_lkp")]
[DisplayNameLocalized(typeof(ResourcesClassBooks), "BookContributorTypeIdDisplayName_lkp")]
public string BookContributorTypeId { get { return _bookContributorTypeId; } set { SetField(ref _bookContributorTypeId, value, "BookContributorTypeId"); } }
private string _bookContributorTypeDescription;
[DescriptionLocalized(typeof(ResourcesClassBooks), "BookContributorTypeComment_lkp")]
[DisplayNameLocalized(typeof(ResourcesClassBooks), "BookContributorTypeDisplayName_lkp")]
public string BookContributorTypeDescription { get { return _bookContributorTypeDescription; } set { SetField(ref _bookContributorTypeDescription, value, "BookContributorTypeDescription"); } }
#region handle property changes
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetField<T>(ref T field, T value, string propertyName)
{
//if the value did not change, do nothing.
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
//the value did change, so make the modification.
field = value;
return true;
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
我现在所有的工作都没有组合框,因为我不知道如何实现组合框来显示BookContributorTypes类的选择选项:
dataGridView1.DataSource = bookContributors;
感谢您提供的帮助。
答案 0 :(得分:0)
我正在使用WinForms DataGridView
多年。 AFAIK DataGridView
并不聪明
如你所料。您必须手动设置comboBox列,
即在事件DataBindingComplete
DataGridViewComboBoxColumn
DataPropertyName
属性设置为"BookContributorType"
DataGridViewColumnCollection
DataSource
属性设置为BookContributorTypes
ValueMember
属性设置为"BookContributorTypeId"
DisplayMember
属性设置为"BookContributorTypeDescription"
BookContributorTypes
列的属性
DisplayIndex
我在DataGridView
周围使用包装器类来获得更智能的控件。通过这种方式,我减少了
源代码我到处都在使用DataGridView
。
以下是使用comboBox列替换自动生成的列的代码段:
DataGridViewColumn auto // = ... auto-generated column to be replaced
DataGridViewComboBoxColumn combo = new DataGridViewComboBoxColumn();
combo.DataPropertyName = auto.DataPropertyName;
combo.Name = auto.Name;
DataGridView dgv = auto.DataGridView;
dgv.Columns.Add(combo);
combo.DataSource = GetBookContributorTypes; // collection of comboBox entries
combo.ValueMember = "BookContributorTypeId";
combo.DisplayMember = "BookContributorTypeDescription";
// adopt further properties if required
combo.Frozen = auto.Frozen;
combo.DisplayIndex = auto.DisplayIndex;
combo.Visible = auto.Visible;
combo.ReadOnly = auto.ReadOnly;
combo.HeaderText = auto.HeaderText;
combo.HeaderCell.ToolTipText = auto.HeaderCell.ToolTipText;
combo.SortMode = auto.SortMode;
combo.Width = auto.Width;
dgv.Columns.Remove(auto);
答案 1 :(得分:0)
这最终比我原先想象的要困难得多。事实证明,如果你想在一个带有组合框的DataGridView中放置一个列并让该组合框与另一个类交互,那么它就不是一个快速的单行。
我的例子有两个类:
BookContributors
(bookContributors
) - 为图书做出贡献的人员列表。例如,这会存储一个人的姓名和他们所做贡献的类型。BookContributorTypes
(bookContributorTypes
) - 书籍可能的贡献类型列表,例如编辑或贡献。ContributorTypes
类成为一个组合框,并将用户的选择存储到BookContributors
类中,特别是BookContributorType
属性。这是我提出的代码,以及我在此过程中发现的一些其他注释。据我所知,我提供的信息是准确的: - )
gvContributors.DataSource = bookContributors; //set the datgridview's datasource so it displays the class you want.
gvContributors.Columns["BookContributorType"].Visible = false; //hide the column (property) you want to replace with a combobox.
DataGridViewComboBoxColumn contribType = new DataGridViewComboBoxColumn(); //create a combobox object.
contribType.HeaderText = "My Column"; //the text to display in the column header.
contribType.Name = "BookContributorType"; //name of the class property you set to Visible=false. Note sure if this is needed.
contribType.DataSource = bookContributorTypes; //name of the class that provides the combobox data.
contribType.DisplayMember = "BookContributorTypeDescription"; //data the user will see when clicking the combobox.
contribType.ValueMember = "BookContributorTypeId"; //data to store in the class property.
contribType.DataPropertyName = "BookContributorType"; //the class property you are binding to in order to store the data.
gvContributors.Columns.Add(contribType); //add the new combobox to the datagridview.
您现在拥有以下内容:
DataGridView
。就我而言,数据源是一个类。Visible=false
)列。DataGridViewComboBox
,以便用户看到值列表。通过使用DataPropertyName
与隐藏列相同的名称,您现在可以绑定到DataGridView的DataSource
。这篇文章的另一个答案表明,您使用组合框替换了Remove
列,但Visible=false
似乎对我有效。
运行解决方案时,您会发现用户必须在组合框上单击两次。我还没有尝试过此代码,但认为这篇文章可以解决这个问题:Open dropdown(in a datagrid view) items on a single click