c# - 在 Windows 窗体 DataGridView 单元格中托管 TreeView

标签 c# .net winforms datagridview

我想为 DataGridView 创建一个 TreeView 列。我遵循了 here 中的示例通过如下扩展 TreeView。

public class TreeViewEditingControl : TreeView, IDataGridViewEditingControl

public class TreeViewCell : DataGridViewComboBoxCell // Not sure whether this should be DataGridViewTextBoxCell

这是我的问题。我可以在单元格中看到 Treeview,但我不知道如何在用户单击单元格时增加 Cell/TreeView 的高度(随着 ComboBox 展开)。有人对此有任何想法吗?

最佳答案

我会生成一个新的无边框窗体,里面有一个 TreeCtrl 停靠在里面,我已经用 CalendarControl 完成了这个并且效果很好。如果将表单的左上角设置为正在编辑的单元格的左上角,用户将不会知道其中的区别。希望这就是您要找的。

编辑:

这是我为文件选择单元所做的实现。它有一个浏览按钮,当您单击它进行编辑并打开一个 FileOpenDialog 时,该按钮会出现在单元格中。代码很长,但我想你可以挑出你需要实现的部分。

public class DataGridViewFileColumn : DataGridViewColumn
{
    public DataGridViewFileColumn() : base(new DataGridViewFileCell())
    {
        BrowseLabel = "...";
        SaveFullPath = false;
    }

    public override DataGridViewCell CellTemplate
    {
        get
        {
            return base.CellTemplate;
        }
        set
        {
            // Ensure that the cell used for the template is a DataGridViewFileCell.
            if (value != null &&
                !value.GetType().IsAssignableFrom(typeof(DataGridViewFileCell)))
            {
                throw new InvalidCastException("Must be a DataGridViewFileCell");
            }
            base.CellTemplate = value;
        }
    }

    [Description("Label to place on Browse button"),Category("Appearance")]
    [DefaultValue("...")]
    public string BrowseLabel 
    {
        get; 
        set; 
    }

    [Description("Save full path name"), Category("Behavior")]
    [DefaultValue(true)]
    public bool SaveFullPath
    {
        get;
        set;
    }
}


public class DataGridViewFileCell : DataGridViewTextBoxCell
{
    public DataGridViewFileCell() : base()
    {
    }

    public override void InitializeEditingControl(int rowIndex, object
            initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
    {
        // Set the value of the editing control to the current cell value.
        base.InitializeEditingControl(rowIndex, initialFormattedValue,
            dataGridViewCellStyle);
        FileEditingControl ctl = (FileEditingControl)DataGridView.EditingControl;
        // Use the default row value when Value property is null.
        if (this.Value == null)
        {
            ctl.Filename = this.DefaultNewRowValue.ToString();
        }
        else
        {
            ctl.Filename = this.Value.ToString();
        }
    }

    public override Type EditType
    {
        get
        {
            // Return the type of the editing control that DataGridViewFileCell uses.
            return typeof(FileEditingControl);
        }
    }

    public override Type ValueType
    {
        get
        {
            // Return the type of the value that DataGridViewFileCell contains.
            return typeof(string);
        }
    }
}

class FileEditingControl : FileTextBox, IDataGridViewEditingControl
{
    DataGridView dataGridView;
    private bool valueChanged = false;
    int rowIndex;

    public FileEditingControl()
    {
    }

    #region IDataGridViewEditingControl implementations
    public object EditingControlFormattedValue
    {
        get
        {
            return Filename;
        }
        set
        {
            if (value is String)
            {
                try
                {
                    Filename = (String)value;
                }
                catch
                {
                    Filename = value.ToString();
                }
            }
        }
    }

    public object GetEditingControlFormattedValue(
        DataGridViewDataErrorContexts context)
    {
        return EditingControlFormattedValue;
    }

    public void ApplyCellStyleToEditingControl(
        DataGridViewCellStyle dataGridViewCellStyle)
    {
        this.Font = dataGridViewCellStyle.Font;
    }

    public int EditingControlRowIndex
    {
        get
        {
            return rowIndex;
        }
        set
        {
            rowIndex = value;
        }
    }

    public bool EditingControlWantsInputKey(
        Keys key, bool dataGridViewWantsInputKey)
    {
        switch (key & Keys.KeyCode)
        {
            case Keys.Left:
            case Keys.Up:
            case Keys.Down:
            case Keys.Right:
            case Keys.Home:
            case Keys.End:
            case Keys.PageDown:
            case Keys.PageUp:
                return true;
            default:
                return !dataGridViewWantsInputKey;
        }
    }

    public void PrepareEditingControlForEdit(bool selectAll)
    {
    }

    public bool RepositionEditingControlOnValueChange
    {
        get
        {
            return false;
        }
    }

    public DataGridView EditingControlDataGridView
    {
        get
        {
            return dataGridView;
        }
        set
        {
            dataGridView = value;
        }
    }

    public bool EditingControlValueChanged
    {
        get
        {
            return valueChanged;
        }
        set
        {
            valueChanged = value;
        }
    }

    public Cursor EditingPanelCursor
    {
        get
        {
            return base.Cursor;
        }
    }
    #endregion

    protected override void OnValueChanged(FileEventArgs eventargs)
    {
        // Notify the DataGridView that the contents of the cell
        // have changed.
        valueChanged = true;
        this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
        base.OnValueChanged(eventargs);
    }
}

public partial class FileTextBox : UserControl
{

    #region Constructors
    public FileTextBox()
    {
        InitializeComponent();
        Tooltip = new ToolTip();

        SaveFullPath = false;
        AllowMultipleFiles = false;
        BrowseLabel = "...";
    }
    #endregion Constructors

    #region Properties
    /// <summary>
    /// Tooltip object used to show full path name
    /// </summary>
    private ToolTip Tooltip;

    /// <summary>
    /// Return the full path or just the filename?
    /// </summary>
    [Description("Save Full Path"), Category("Behavior")]
    [DefaultValue(false)]
    public bool SaveFullPath
    {
        get;
        set;
    }

    /// <summary>
    /// String representing the filename for this control
    /// </summary>
    public override string Text
    {
        get 
        { 
            return base.Text; 
        }
        set 
        {
            if (base.Text != value)
            {
                base.Text = value;
                Tooltip.SetToolTip(this, base.Text);
                Invalidate();
                OnValueChanged(new FileEventArgs(base.Text));
            }
        }
    }

    [Description("Browse Label"), Category("Appearance")]
    [DefaultValue("...")]
    public string BrowseLabel
    {
        get
        {
            return Browse.Text;
        }
        set
        {
            Browse.Text = value;
            Browse.Width = TextRenderer.MeasureText(Browse.Text, Browse.Font).Width + 8;
            Browse.Location = new Point(this.Width - Browse.Width, Browse.Location.Y);
        }
    }

    [Description("Allow Multiple Files"), Category("Behavior")]
    [DefaultValue(false)]
    public bool AllowMultipleFiles
    {
        get;
        set;
    }

    /// <summary>
    /// Selected filename (same as Text property)
    /// </summary>
    [Description("Filename"), Category("Data")]
    public string Filename
    {
        get { return Text; }
        set { Text = value; }
    }
    #endregion Properties

    #region Event Handlers
    /// <summary>
    /// Event raised when 
    /// </summary>
    public event EventHandler ValueChanged;
    protected virtual void OnValueChanged(FileEventArgs eventargs)
    {
        eventargs.Filename = Filename;
        if (this.ValueChanged != null)
            this.ValueChanged(this, eventargs);
    }

    private void Browse_Click(object sender, EventArgs e)
    {
        OpenFileDialog dlg = new OpenFileDialog();
        dlg.FileName = Text;

        dlg.Multiselect = AllowMultipleFiles;
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            if (SaveFullPath)
                Text = dlg.FileName;
            else
                Text = dlg.SafeFileName;
        }
    } 

    protected override void OnPaint(PaintEventArgs e)
    {
        // Draw the client window
        Rectangle r = new Rectangle(new Point(0, 0), new Size(Size.Width-1, Size.Height-1));
        Graphics g = e.Graphics;
        g.FillRectangle(new SolidBrush(SystemColors.Window), r);
        g.DrawRectangle(new Pen(VisualStyleInformation.TextControlBorder), r);
        r.Y += Margin.Top;
        r.Width -= Browse.Width;

        // Fill with Text
        TextRenderer.DrawText(g, Text, Font, r, ForeColor, TextFormatFlags.PathEllipsis);

        base.OnPaint(e);
    }

    private void FileTextBox_DragDrop(object sender, DragEventArgs e)
    {
        DataObject data = (DataObject)e.Data;
        StringCollection filenames = data.GetFileDropList();

        if ( filenames.Count == 1)
            Text = filenames[0];
    }

    private void FileTextBox_DragEnter(object sender, DragEventArgs e)
    {
        DataObject data = (DataObject)e.Data;
        StringCollection filenames = data.GetFileDropList();

        if (/*!AllowMultipleFiles &&*/ filenames.Count == 1)
            e.Effect = DragDropEffects.Link;
    }
    #endregion Event Handlers

}

public class FileEventArgs : EventArgs
{
    public FileEventArgs(string Text)
    {
        Filename = Text;
    }

    /// <summary>
    /// Name of the file in the control
    /// </summary>
    public String Filename { get; set; }
}

关于c# - 在 Windows 窗体 DataGridView 单元格中托管 TreeView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10678649/

相关文章:

c# - 有没有办法压缩内存中的对象并透明地使用它?

c# - Regex C# - 获取文本中所有出现的地方

c# - 在运行时向动态对象添加成员

c# - 如何创建一个可以在其中放置其他控件的 UserControl?

c# - 实现相同方法的表单

c# - 想要在我的 C# 应用程序中显示可视通知

c# - 从服务引用 C# 中获取地址

c# - 快速查找遭受浮点不准确

c# - 在 XmlNodeList 上使用 LINQ

c# - 库的 Pdb 文件未加载到应用程序的 bin 文件夹中