From WxWiki
Jump to: navigation, search
Official Classes SmallBlocks.png Archive Containers Controls Data Structures Database Date & Time Debug Device Contexts Dialogs Document & Views Drag & Drop Events Filesystem Frames Graphics Grid Cell Help HTML Logging Miscellaneous Networking Printing Sizers Streams Threading Windows

wxDataViewCtrl is a control to display data either in a tree like fashion or in a tabular form or both.

If you only need to display a simple tree structure with an API more like the older wxTreeCtrl class, then the specialized wxDataViewTreeCtrl can be used. Likewise, if you only want to display simple table structure you can use the specialized wxDataViewListCtrl class. Both wxDataViewTreeCtrl and wxDataViewListCtrl can be used without defining your own wxDataViewModel.

A wxDataViewItem is used to represent a (visible) item in the control.

Unlike wxListCtrl, wxDataViewCtrl doesn't get its data from the user through virtual functions or by setting it directly. Instead you need to write your own wxDataViewModel and associate it with this control. Then you need to add a number of wxDataViewColumn to this control to define what each column shall display. Each wxDataViewColumn in turn owns 1 instance of a wxDataViewRenderer to render its cells.

A number of standard renderers for rendering text, dates, images, toggle, a progress bar etc. are provided. Additionally, the user can write custom renderers deriving from wxDataViewCustomRenderer for displaying anything.

All data transfer from the control to the model and the user code is done through wxVariant which can be extended to support more data formats as necessary. Accordingly, all type information uses the strings returned from wxVariant::GetType.

Note: This is new in 2.9.1


Here is an example of how to use wxDataViewCtrl.

    #include <wx/wx.h>
    #include <wx/dataview.h>
    #include <wx/hashset.h>
    enum Identifiers {
        IDTREEAPP = wxID_HIGHEST + 1,
        IDDATAVIEW = wxID_HIGHEST + 2,
        IDREDO = wxID_HIGHEST + 3
    WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual, StringHash);
    StringHash strings;
    wxStringCharType* asPointer(const wxString s) {
        if (s.length() < 2) {
            return NULL;
        StringHash::iterator it = strings.find(s);
        assert(it != strings.end());
        wxStringCharType* res = const_cast<wxStringCharType* >(it->wx_str());
        return res;
    class TestModel: public wxDataViewModel {
        TestModel(): wxDataViewModel(), topic(0) {}
        ~TestModel() {}
        unsigned int GetColumnCount() const {
            return 1;
        wxString GetColumnType(unsigned int column) const {
            return "string";
        void GetValue(wxVariant& val, const wxDataViewItem& item, unsigned int column) const {
            wxVariant v(_asString(item));
            val = v;
        bool SetValue(const wxVariant& val, const wxDataViewItem& item, unsigned int column) {
            return true;
        wxDataViewItem GetParent(const wxDataViewItem& item) const {
            wxString par = _asString(item);
            if (par.length() != 1) {
                return wxDataViewItem(asPointer(par.Left(par.length() - 1)));
            return wxDataViewItem(NULL);
        bool IsContainer(const wxDataViewItem& item) const {
            wxString par = _asString(item);
            return (par.length() < 3);
        unsigned GetChildren(const wxDataViewItem& item, wxDataViewItemArray& children) const {
            wxString par = _asString(item);
            if (topic == 0 or par.length() == 3) {
                return 0;
            children.Add(wxDataViewItem(asPointer(par + "a")));
            children.Add(wxDataViewItem(asPointer(par + "b")));
            children.Add(wxDataViewItem(asPointer(par + "c")));
            return 3;
        void setTopic(int ptopic) {
            topic = ptopic;
            if (topic > 1) {
        int topic;
        wxString _asString(const wxDataViewItem& item) const {
            if (item.IsOk()) {
                return static_cast<wxStringCharType*>(item.GetID());
            wxStringCharType ch = 'A' + topic;
            return wxString(ch);
    class TreeFrame: public wxFrame {
        TreeFrame(const wxString& title, const wxPoint& pos, const wxSize& size):
            wxFrame(NULL, IDTREEAPP, title, pos, size) {
            _sizer = new wxFlexGridSizer(1, 3, 3);
            dataView = new wxDataViewCtrl(this, IDDATAVIEW, wxDefaultPosition, wxSize(300, 300), wxDV_NO_HEADER | wxDV_VARIABLE_LINE_HEIGHT);
            wxDataViewTextRenderer* rend0 = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_EDITABLE);
            _column0 = new wxDataViewColumn("string", rend0, 0, 100, wxAlignment(wxALIGN_LEFT | wxALIGN_TOP), wxDATAVIEW_COL_RESIZABLE);
            _redoButton = new wxButton(this, IDREDO, "Redo");
        void onRedo(wxCommandEvent& event) {
            testModel->setTopic(testModel->topic + 1);
        TestModel* testModel;
        wxDataViewCtrl* dataView;
        wxFlexGridSizer* _sizer;
        wxDataViewColumn* _column0;
        wxButton* _redoButton;
    BEGIN_EVENT_TABLE(TreeFrame, wxFrame)
        EVT_BUTTON(IDREDO, TreeFrame::onRedo)
    class TreeApp: public wxApp {
        virtual bool OnInit() {
            if (!wxApp::OnInit()) {
                return false;
            _treeFrame = new TreeFrame("Test tree frame", wxPoint(50, 50), wxSize(300, 300));
            _treeFrame->testModel = new TestModel;
            return true;
        TreeFrame* _treeFrame;

See Also