关联两个类,以便组合框与第二个类一起显示

本文关键字:组合 第二个 显示 一起 关联 两个 | 更新日期: 2023-09-27 18:33:38

我有一个Winforms应用程序。有两个类。一个类存储为书籍做出贡献的人员。另一个类是可能的贡献类型(如编辑者、审阅者等(的列表。

BookContributors 类是我的 datagridview 的数据源,工作得很好。现在,我想让 BookContributorTypes 类成为为 BookContributors 类提供信息的组合框。

到目前为止,在我的阅读中,看起来我有很多选择,包括强制组合框进入 datagridview,使用类属性,在类之间创建一对多关系。

由于我的代码将有许多此类情况,因此我想正确地执行此操作。我认为这意味着以某种方式显示两个类之间的关系,以便 datagridview 知道只显示组合框,但我不确定如何做到这一点。

图书投稿人

由填写投稿人的人填充。例:书籍贡献者="约翰·史密斯";BookContributorFileAs="Smith, John";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
}

BookContributorType(填充 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
}

我现在所做的一切,没有组合框,因为我不知道如何实现组合框来显示 BookContributorType 类中的选择选项:

dataGridView1.DataSource = bookContributors;

感谢您提供的帮助。

关联两个类,以便组合框与第二个类一起显示

这最终比我最初想象的要困难得多。事实证明,如果要使用组合框在 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.

您现在拥有的是以下内容:

  1. 具有数据源的DataGridView。就我而言,数据源是一个类。
  2. 要制作组合框的隐藏(Visible=false(列。
  3. 链接到另一个数据源的DataGridViewComboBox,以便用户看到值列表。通过将DataPropertyName用作与隐藏列相同的名称,您现在绑定到 DataGridView 的DataSource

这篇文章的另一个答案建议你Remove用组合框替换的列,但Visible=false似乎对我有用。

运行解决方案时,您会发现用户必须在组合框上单击两次。我还没有尝试过这段代码,但认为这篇文章会解决这个问题: 单击一下即可打开下拉列表(在数据网格视图中(项目

我在WinForms DataGridView工作了好几年。AFAIK DataGridView没有那么聪明如您所料。您必须手动设置 comboBox 列,即在事件DataBindingComplete

  • 创建新DataGridViewComboBoxColumn
  • 将其DataPropertyName属性设置为 "BookContributorType"
  • 将其添加到DataGridViewColumnCollection
  • 将其 DataSource 属性设置为BookContributorTypes集合
  • 将其ValueMember属性设置为 "BookContributorTypeId"
  • 将其DisplayMember属性设置为 "BookContributorTypeDescription"
  • 采用自动生成的列中的属性,BookContributorTypesDisplayIndex
  • 删除自动生成的列

我正在使用包装类来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);