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

时间:2016-02-08 15:07:04

标签: c# winforms class datagridview combobox

我有一个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;

感谢您提供的帮助。

2 个答案:

答案 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中放置一个列并让该组合框与另一个类交互,那么它就不是一个快速的单行。

我的例子有两个类:

  • BookContributorsbookContributors) - 为图书做出贡献的人员列表。例如,这会存储一个人的姓名和他们所做贡献的类型。
  • BookContributorTypesbookContributorTypes) - 书籍可能的贡献类型列表,例如编辑贡献
  • 我希望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
  4. 这篇文章的另一个答案表明,您使用组合框替换了Remove列,但Visible=false似乎对我有效。

    运行解决方案时,您会发现用户必须在组合框上单击两次。我还没有尝试过此代码,但认为这篇文章可以解决这个问题:Open dropdown(in a datagrid view) items on a single click