wxDataView tree view not showing any tree nodes Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
sw
Experienced Solver
Experienced Solver
Posts: 56
Joined: Sat Mar 16, 2019 8:09 pm

wxDataView tree view not showing any tree nodes

Post by sw »

I am trying to create a wxDataViewCtrl that looks similar to the MyMusicTreeModel in the dataview sample.

My issue is that with what I'm doing I get the wxDataViewCtrl to show with the columns, but I'm not able to see the tree node data on the control at all.

In addition to that, closing the application causes a Read Access Violation in datavcmn.cpp

Code: Select all

wxDataViewColumnBase::~wxDataViewColumnBase()
{
    delete m_renderer; // read access violation here
}
I have attached a sample which shows this behavior (No tree node data and read access violation). As far as I can tell I'm doing what is being done in the samples and I don't see any fundamental difference.

Code: Select all

#include <wx/wx.h>
#include <wx/dataview.h>

class MyTreeModelNode;
WX_DEFINE_ARRAY_PTR(MyTreeModelNode*, MyTreeModelNodePtrArray);

class MyTreeModelNode final
{
public:
    MyTreeModelNode(MyTreeModelNode* parent,
        int id,
        const wxString& column1,
        const wxString& column2,
        const wxString& column3,
        const wxString& column4);
    MyTreeModelNode(MyTreeModelNode* parent, const wxString& branch);
    ~MyTreeModelNode();

    bool IsContainer() const;
    MyTreeModelNode* GetParent();
    MyTreeModelNodePtrArray& GetChildren();
    MyTreeModelNode* GetNthChild(unsigned int n);

    void Insert(MyTreeModelNode* child, unsigned int n);
    void Append(MyTreeModelNode* child);
    const unsigned int GetChildCount() const;

    int GetId() const;
    wxString GetColumn1() const;
    wxString GetColumn2() const;
    wxString GetColumn3() const;
    wxString GetColumn4() const;

    void SetId(int value);
    void SetColumn1(const wxString& value);
    void SetColumn2(const wxString& value);
    void SetColumn3(const wxString& value);
    void SetColumn4(const wxString& value);

private:
    MyTreeModelNode* pParent;
    MyTreeModelNodePtrArray mChildren;

    int mId;
    wxString mColumn1;
    wxString mColumn2;
    wxString mColumn3;
    wxString mColumn4;
    bool bContainer;
};

MyTreeModelNode::MyTreeModelNode(MyTreeModelNode* parent,
    int id,
    const wxString& column1,
    const wxString& column2,
    const wxString& column3,
    const wxString& column4)
    : pParent(parent)
    , mId(id)
    , mColumn1(column1)
    , mColumn2(column2)
    , mColumn3(column3)
    , mColumn4(column4)
    , bContainer(false)
{
}

MyTreeModelNode::MyTreeModelNode(MyTreeModelNode* parent, const wxString& branch)
    : pParent(parent)
    , mColumn1(branch)
    , bContainer(true)
{
}

MyTreeModelNode::~MyTreeModelNode()
{
    std::size_t count = mChildren.GetCount();
    for (std::size_t i = 0; i < count; i++) {
        MyTreeModelNode* child = mChildren[i];
        delete child;
    }
}

bool MyTreeModelNode::IsContainer() const
{
    return bContainer;
}

MyTreeModelNode* MyTreeModelNode::GetParent()
{
    return pParent;
}

MyTreeModelNodePtrArray& MyTreeModelNode::GetChildren()
{
    return mChildren;
}

MyTreeModelNode* MyTreeModelNode::GetNthChild(unsigned int n)
{
    return mChildren.Item(n);
}

void MyTreeModelNode::Insert(MyTreeModelNode* child, unsigned int n)
{
    mChildren.Insert(child, n);
}

void MyTreeModelNode::Append(MyTreeModelNode* child)
{
    mChildren.Add(child);
}

const unsigned int MyTreeModelNode::GetChildCount() const
{
    return mChildren.Count();
}

int MyTreeModelNode::GetId() const
{
    return mId;
}

wxString MyTreeModelNode::GetColumn1() const
{
    return mColumn1;
}

wxString MyTreeModelNode::GetColumn2() const
{
    return mColumn2;
}

wxString MyTreeModelNode::GetColumn3() const
{
    return mColumn3;
}

wxString MyTreeModelNode::GetColumn4() const
{
    return mColumn4;
}

void MyTreeModelNode::SetId(int value)
{
    mId = value;
}

void MyTreeModelNode::SetColumn1(const wxString& value)
{
    mColumn1 = value;
}

void MyTreeModelNode::SetColumn2(const wxString& value)
{
    mColumn2 = value;
}

void MyTreeModelNode::SetColumn3(const wxString& value)
{
    mColumn3 = value;
}

void MyTreeModelNode::SetColumn4(const wxString& value)
{
    mColumn4 = value;
}

class MyTreeModel : public wxDataViewModel
{
public:
    enum {
        Col_Id = 0,
        Col_Column1,
        Col_Column2,
        Col_Column3,
        Col_Column4,
        Col_Max
    };

    MyTreeModel();
    ~MyTreeModel();

    unsigned int GetColumnCount() const override;
    wxString GetColumnType(unsigned int col) const override;
    void GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const override;
    bool SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col) override;
    bool IsEnabled(const wxDataViewItem& item, unsigned int col) const override;
    wxDataViewItem GetParent(const wxDataViewItem& item) const override;
    bool IsContainer(const wxDataViewItem& item) const override;
    unsigned int GetChildren(const wxDataViewItem& parent, wxDataViewItemArray& array) const override;

private:
    MyTreeModelNode* pRoot;
    MyTreeModelNode* pDataSet1;
    MyTreeModelNode* pDataSet2;
};


MyTreeModel::MyTreeModel()
{
    pRoot = new MyTreeModelNode(nullptr, wxT("Data Overview"));

    pDataSet1 = new MyTreeModelNode(pRoot, wxT("Data Set #1"));

    auto nodeDataSet1 = new MyTreeModelNode(pRoot, 455, "A data set", "describes", "useful", "information to a end user (hopefully)");
    pDataSet1->Append(nodeDataSet1);

    pRoot->Append(pDataSet1);

    pDataSet2 = new MyTreeModelNode(pRoot, wxT("Data Set #2"));
    pRoot->Append(pDataSet2);
}

MyTreeModel::~MyTreeModel()
{
    delete pRoot;
}

unsigned int MyTreeModel::GetColumnCount() const
{
    return Col_Max;
}

wxString MyTreeModel::GetColumnType(unsigned int col) const
{
    if (col == Col_Id) {
        return "long";
    }
    else {
        return "string";
    }
}

void MyTreeModel::GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const
{
    wxASSERT(item.IsOk());

    MyTreeModelNode* node = (MyTreeModelNode*)item.GetID();
    switch (col) {
    case Col_Id:
        variant = (long)node->GetId();
        break;
    case Col_Column1:
        variant = node->GetColumn1();
        break;
    case Col_Column2:
        variant = node->GetColumn2();
        break;
    case Col_Column3:
        variant = node->GetColumn3();
        break;
    case Col_Column4:
        variant = node->GetColumn4();
        break;
    case Col_Max:
    default:
        wxLogError("MyTreeModel::GetValue: wrong column %d", col);
        break;
    }
}

bool MyTreeModel::SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col)
{
    wxASSERT(item.IsOk());

    MyTreeModelNode* node = (MyTreeModelNode*)item.GetID();
    switch (col) {
    case Col_Id:
        node->SetId(variant.GetInteger());
        break;
    case Col_Column1:
        node->SetColumn1(variant.GetString());
        break;
    case Col_Column2:
        node->SetColumn2(variant.GetString());
        break;
    case Col_Column3:
        node->SetColumn3(variant.GetString());
        break;
    case Col_Column4:
        node->SetColumn4(variant.GetString());
        break;
    case Col_Max:
    default:
        wxLogError("MyTreeModel::SetValue: wrong column %d", col);
        break;
    }

    return false;
}

bool MyTreeModel::IsEnabled(const wxDataViewItem& item, unsigned int col) const
{
    return true;
}

wxDataViewItem MyTreeModel::GetParent(const wxDataViewItem& item) const
{
    if (!item.IsOk()) {
        return wxDataViewItem(0);
    }

    MyTreeModelNode* node = (MyTreeModelNode*)item.GetID();

    if (node == pRoot) {
        return wxDataViewItem(0);
    }

    return wxDataViewItem((void*)node->GetParent());
}

bool MyTreeModel::IsContainer(const wxDataViewItem& item) const
{
    if (!item.IsOk()) {
        return true;
    }

    MyTreeModelNode* node = (MyTreeModelNode*)item.GetID();
    return node->IsContainer();
}

unsigned int MyTreeModel::GetChildren(const wxDataViewItem& parent, wxDataViewItemArray& array) const
{
    MyTreeModelNode* node = (MyTreeModelNode*)parent.GetID();
    if (!node) {
        array.Add(wxDataViewItem((void*)pRoot));
        return 1;
    }

    if (node->GetChildCount() == 0) {
        return 0;
    }

    unsigned int count = node->GetChildren().GetCount();
    for (unsigned int pos = 0; pos < count; pos++) {
        MyTreeModelNode* child = node->GetChildren().Item(pos);
        array.Add(wxDataViewItem((void*)child));
    }

    return count;
}

class MainFrame final : public wxFrame
{
public:
    MainFrame();

    virtual ~MainFrame() = default;

private:
    void CreateControls();
    wxObjectDataPtr<MyTreeModel> pMyTreeModel;
    wxDataViewCtrl* pDataViewCtrl;

    enum { IDC_DATAVIEW = wxID_HIGHEST + 1 };

};

MainFrame::MainFrame()
    : wxFrame(nullptr, wxID_ANY, wxT("wxWidgets Dataview Example"))
{
    CreateControls();
}

void MainFrame::CreateControls()
{
    auto mainPanel = new wxPanel(this, wxID_ANY);

    auto mainSizer = new wxBoxSizer(wxVERTICAL);
    mainPanel->SetSizer(mainSizer);

    /* Data View Ctrl */
    long style = wxDV_SINGLE | wxDV_ROW_LINES | wxDV_HORIZ_RULES | wxDV_VERT_RULES;
    pDataViewCtrl = new wxDataViewCtrl(mainPanel, IDC_DATAVIEW, wxDefaultPosition, wxDefaultSize, style);
    mainSizer->Add(pDataViewCtrl, 1, wxEXPAND | wxALL, 5);

    /* Data View Model */
    pMyTreeModel = new MyTreeModel();
    pDataViewCtrl->AssociateModel(pMyTreeModel.get());

    /* Data View Columns */
    auto dataViewTextRenderer = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT);
    auto dataViewIntRenderer = new wxDataViewTextRenderer("long", wxDATAVIEW_CELL_INERT);

    /* ID Column */
    auto idColumn = new wxDataViewColumn(
        wxT("ID"), dataViewIntRenderer, MyTreeModel::Col_Id, 32, wxALIGN_CENTER, wxDATAVIEW_COL_HIDDEN);
    pDataViewCtrl->AppendColumn(idColumn);

    auto column1 = new wxDataViewColumn(wxT("Column 1"),
        dataViewTextRenderer,
        MyTreeModel::Col_Column1,
        80,
        wxALIGN_LEFT,
        wxDATAVIEW_COL_RESIZABLE);
    column1->SetWidth(wxCOL_WIDTH_AUTOSIZE);
    pDataViewCtrl->AppendColumn(column1);

    auto column2 =
        new wxDataViewColumn(wxT("Column 2"), dataViewTextRenderer, MyTreeModel::Col_Column2);
    column2->SetWidth(wxCOL_WIDTH_AUTOSIZE);
    column2->SetResizeable(false);
    pDataViewCtrl->AppendColumn(column2);

    auto column3 = new wxDataViewColumn(wxT("Column 3"),
        dataViewTextRenderer,
        MyTreeModel::Col_Column3,
        80,
        wxALIGN_CENTER,
        wxDATAVIEW_COL_RESIZABLE);
    column3->SetWidth(wxCOL_WIDTH_AUTOSIZE);
    pDataViewCtrl->AppendColumn(column3);

    auto column4 = new wxDataViewColumn(wxT("Column 4"),
        dataViewTextRenderer,
        MyTreeModel::Col_Column4,
        80,
        wxALIGN_LEFT,
        wxDATAVIEW_COL_RESIZABLE);
    pDataViewCtrl->AppendColumn(column4);
}

class Application : public wxApp
{
public:
    Application();
    virtual ~Application() = default;

    bool OnInit() override;
};

Application::Application()
{
}

bool Application::OnInit()
{
    auto frame = new MainFrame();
    frame->Show(true);
    SetTopWindow(frame);

    return true;
}

wxIMPLEMENT_APP(Application);
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataView tree view not showing any tree nodes

Post by doublemax »

I can only tell you why it crashes: Each column owns its renderer, so you can't pass the same renderer pointer to multiple columns.

As for the content not showing up, it's probably something trivial too, but it's just too much code to read :)

I would suggest to put debug output into methods like IsContainer/GetChildren etc. and check if they are called and what they return. Also double check the signatures of all virtual methods.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7458
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxDataView tree view not showing any tree nodes

Post by ONEEYEMAN »

doublemax,
Its quite possible that fixing the crash will make the other problem disappear, and the nodes will appear.

BTW, I'm not a poet. ;-)

Thank yuo.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxDataView tree view not showing any tree nodes

Post by doublemax »

I think wxDATAVIEW_COL_HIDDEN for the first column is the issue. Remove this or expand the root item programmatically.
Use the source, Luke!
sw
Experienced Solver
Experienced Solver
Posts: 56
Joined: Sat Mar 16, 2019 8:09 pm

Re: wxDataView tree view not showing any tree nodes

Post by sw »

It was indeed the first column with wxDATAVIEW_COL_HIDDEN flag which was the problem. I moved it to be the last column (and hidden still) and I can see my tree data. And I created renderer's for each column and that fixed the crash too.

Thanks doublemax and ONEEYEMAN

Here is the working code in case anyone is interested:

Code: Select all

#include <wx/wx.h>
#include <wx/dataview.h>

class MyTreeModelNode;
WX_DEFINE_ARRAY_PTR(MyTreeModelNode*, MyTreeModelNodePtrArray);

class MyTreeModelNode final
{
public:
    MyTreeModelNode(MyTreeModelNode* parent,
        int id,
        const wxString& column1,
        const wxString& column2,
        const wxString& column3,
        const wxString& column4);
    MyTreeModelNode(MyTreeModelNode* parent, const wxString& branch);
    ~MyTreeModelNode();

    bool IsContainer() const;
    MyTreeModelNode* GetParent();
    MyTreeModelNodePtrArray& GetChildren();
    MyTreeModelNode* GetNthChild(unsigned int n);

    void Insert(MyTreeModelNode* child, unsigned int n);
    void Append(MyTreeModelNode* child);
    const unsigned int GetChildCount() const;

    int GetId() const;
    wxString GetColumn1() const;
    wxString GetColumn2() const;
    wxString GetColumn3() const;
    wxString GetColumn4() const;

    void SetId(int value);
    void SetColumn1(const wxString& value);
    void SetColumn2(const wxString& value);
    void SetColumn3(const wxString& value);
    void SetColumn4(const wxString& value);

private:
    MyTreeModelNode* pParent;
    MyTreeModelNodePtrArray mChildren;

    int mId;
    wxString mColumn1;
    wxString mColumn2;
    wxString mColumn3;
    wxString mColumn4;
    bool bContainer;
};

MyTreeModelNode::MyTreeModelNode(MyTreeModelNode* parent,
    int id,
    const wxString& column1,
    const wxString& column2,
    const wxString& column3,
    const wxString& column4)
    : pParent(parent)
    , mId(id)
    , mColumn1(column1)
    , mColumn2(column2)
    , mColumn3(column3)
    , mColumn4(column4)
    , bContainer(false)
{
}

MyTreeModelNode::MyTreeModelNode(MyTreeModelNode* parent, const wxString& branch)
    : pParent(parent)
    , mColumn1(branch)
    , bContainer(true)
{
}

MyTreeModelNode::~MyTreeModelNode()
{
    std::size_t count = mChildren.GetCount();
    for (std::size_t i = 0; i < count; i++) {
        MyTreeModelNode* child = mChildren[i];
        delete child;
    }
}

bool MyTreeModelNode::IsContainer() const
{
    return bContainer;
}

MyTreeModelNode* MyTreeModelNode::GetParent()
{
    return pParent;
}

MyTreeModelNodePtrArray& MyTreeModelNode::GetChildren()
{
    return mChildren;
}

MyTreeModelNode* MyTreeModelNode::GetNthChild(unsigned int n)
{
    return mChildren.Item(n);
}

void MyTreeModelNode::Insert(MyTreeModelNode* child, unsigned int n)
{
    mChildren.Insert(child, n);
}

void MyTreeModelNode::Append(MyTreeModelNode* child)
{
    mChildren.Add(child);
}

const unsigned int MyTreeModelNode::GetChildCount() const
{
    return mChildren.Count();
}

int MyTreeModelNode::GetId() const
{
    return mId;
}

wxString MyTreeModelNode::GetColumn1() const
{
    return mColumn1;
}

wxString MyTreeModelNode::GetColumn2() const
{
    return mColumn2;
}

wxString MyTreeModelNode::GetColumn3() const
{
    return mColumn3;
}

wxString MyTreeModelNode::GetColumn4() const
{
    return mColumn4;
}

void MyTreeModelNode::SetId(int value)
{
    mId = value;
}

void MyTreeModelNode::SetColumn1(const wxString& value)
{
    mColumn1 = value;
}

void MyTreeModelNode::SetColumn2(const wxString& value)
{
    mColumn2 = value;
}

void MyTreeModelNode::SetColumn3(const wxString& value)
{
    mColumn3 = value;
}

void MyTreeModelNode::SetColumn4(const wxString& value)
{
    mColumn4 = value;
}

class MyTreeModel : public wxDataViewModel
{
public:
    enum {
        Col_Column1 = 0,
        Col_Column2,
        Col_Column3,
        Col_Column4,
        Col_Id,
        Col_Max
    };

    MyTreeModel();
    ~MyTreeModel();

    unsigned int GetColumnCount() const override;
    wxString GetColumnType(unsigned int col) const override;
    void GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const override;
    bool SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col) override;
    bool IsEnabled(const wxDataViewItem& item, unsigned int col) const override;
    wxDataViewItem GetParent(const wxDataViewItem& item) const override;
    bool IsContainer(const wxDataViewItem& item) const override;
    unsigned int GetChildren(const wxDataViewItem& parent, wxDataViewItemArray& array) const override;

private:
    MyTreeModelNode* pRoot;
    MyTreeModelNode* pDataSet1;
    MyTreeModelNode* pDataSet2;
};


MyTreeModel::MyTreeModel()
{
    pRoot = new MyTreeModelNode(nullptr, wxT("Data Overview"));

    pDataSet1 = new MyTreeModelNode(pRoot, wxT("Data Set #1"));

    auto nodeDataSet1 = new MyTreeModelNode(pRoot, 455, "A data set", "describes", "useful", "information to a end user (hopefully)");
    pDataSet1->Append(nodeDataSet1);

    pRoot->Append(pDataSet1);

    pDataSet2 = new MyTreeModelNode(pRoot, wxT("Data Set #2"));
    pRoot->Append(pDataSet2);
}

MyTreeModel::~MyTreeModel()
{
    delete pRoot;
}

unsigned int MyTreeModel::GetColumnCount() const
{
    return Col_Max;
}

wxString MyTreeModel::GetColumnType(unsigned int col) const
{
    if (col == Col_Id) {
        return "long";
    }
    else {
        return "string";
    }
}

void MyTreeModel::GetValue(wxVariant& variant, const wxDataViewItem& item, unsigned int col) const
{
    wxASSERT(item.IsOk());

    MyTreeModelNode* node = (MyTreeModelNode*)item.GetID();
    switch (col) {
    case Col_Column1:
        variant = node->GetColumn1();
        break;
    case Col_Column2:
        variant = node->GetColumn2();
        break;
    case Col_Column3:
        variant = node->GetColumn3();
        break;
    case Col_Column4:
        variant = node->GetColumn4();
        break;
    case Col_Id:
        variant = (long)node->GetId();
        break;
    case Col_Max:
    default:
        wxLogError("MyTreeModel::GetValue: wrong column %d", col);
        break;
    }
}

bool MyTreeModel::SetValue(const wxVariant& variant, const wxDataViewItem& item, unsigned int col)
{
    wxASSERT(item.IsOk());

    MyTreeModelNode* node = (MyTreeModelNode*)item.GetID();
    switch (col) {
    case Col_Column1:
        node->SetColumn1(variant.GetString());
        break;
    case Col_Column2:
        node->SetColumn2(variant.GetString());
        break;
    case Col_Column3:
        node->SetColumn3(variant.GetString());
        break;
    case Col_Column4:
        node->SetColumn4(variant.GetString());
        break;
    case Col_Id:
        node->SetId(variant.GetInteger());
        break;
    case Col_Max:
    default:
        wxLogError("MyTreeModel::SetValue: wrong column %d", col);
        break;
    }

    return false;
}

bool MyTreeModel::IsEnabled(const wxDataViewItem& item, unsigned int col) const
{
    return true;
}

wxDataViewItem MyTreeModel::GetParent(const wxDataViewItem& item) const
{
    if (!item.IsOk()) {
        return wxDataViewItem(0);
    }

    MyTreeModelNode* node = (MyTreeModelNode*)item.GetID();

    if (node == pRoot) {
        return wxDataViewItem(0);
    }

    return wxDataViewItem((void*)node->GetParent());
}

bool MyTreeModel::IsContainer(const wxDataViewItem& item) const
{
    if (!item.IsOk()) {
        return true;
    }

    MyTreeModelNode* node = (MyTreeModelNode*)item.GetID();
    return node->IsContainer();
}

unsigned int MyTreeModel::GetChildren(const wxDataViewItem& parent, wxDataViewItemArray& array) const
{
    MyTreeModelNode* node = (MyTreeModelNode*)parent.GetID();
    if (!node) {
        array.Add(wxDataViewItem((void*)pRoot));
        return 1;
    }

    if (node->GetChildCount() == 0) {
        return 0;
    }

    unsigned int count = node->GetChildren().GetCount();
    for (unsigned int pos = 0; pos < count; pos++) {
        MyTreeModelNode* child = node->GetChildren().Item(pos);
        array.Add(wxDataViewItem((void*)child));
    }

    return count;
}

class MainFrame final : public wxFrame
{
public:
    MainFrame();

    virtual ~MainFrame() = default;

private:
    void CreateControls();
    wxObjectDataPtr<MyTreeModel> pMyTreeModel;
    wxDataViewCtrl* pDataViewCtrl;

    enum { IDC_DATAVIEW = wxID_HIGHEST + 1 };

};

MainFrame::MainFrame()
    : wxFrame(nullptr, wxID_ANY, wxT("wxWidgets Dataview Example"))
{
    CreateControls();
}

void MainFrame::CreateControls()
{
    auto mainPanel = new wxPanel(this, wxID_ANY);

    auto mainSizer = new wxBoxSizer(wxVERTICAL);
    mainPanel->SetSizer(mainSizer);

    /* Data View Ctrl */
    long style = wxDV_SINGLE | wxDV_ROW_LINES | wxDV_HORIZ_RULES | wxDV_VERT_RULES;
    pDataViewCtrl = new wxDataViewCtrl(mainPanel, IDC_DATAVIEW, wxDefaultPosition, wxDefaultSize, style);
    mainSizer->Add(pDataViewCtrl, 1, wxEXPAND | wxALL, 5);

    /* Data View Model */
    pMyTreeModel = new MyTreeModel();
    pDataViewCtrl->AssociateModel(pMyTreeModel.get());

    /* Data View Columns */
    auto column1TextRenderer = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT);
    auto column2TextRenderer = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT);
    auto column3TextRenderer = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT);
    auto column4TextRenderer = new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT);
    auto idColumnRenderer = new wxDataViewTextRenderer("long", wxDATAVIEW_CELL_INERT);

    auto column1 = new wxDataViewColumn(wxT("Column 1"),
        column1TextRenderer,
        MyTreeModel::Col_Column1,
        80,
        wxALIGN_LEFT,
        wxDATAVIEW_COL_RESIZABLE);
    column1->SetWidth(wxCOL_WIDTH_AUTOSIZE);
    pDataViewCtrl->AppendColumn(column1);

    auto column2 =
        new wxDataViewColumn(wxT("Column 2"), column2TextRenderer, MyTreeModel::Col_Column2);
    column2->SetWidth(wxCOL_WIDTH_AUTOSIZE);
    column2->SetResizeable(false);
    pDataViewCtrl->AppendColumn(column2);

    auto column3 = new wxDataViewColumn(wxT("Column 3"),
        column3TextRenderer,
        MyTreeModel::Col_Column3,
        80,
        wxALIGN_CENTER,
        wxDATAVIEW_COL_RESIZABLE);
    column3->SetWidth(wxCOL_WIDTH_AUTOSIZE);
    pDataViewCtrl->AppendColumn(column3);

    auto column4 = new wxDataViewColumn(wxT("Column 4"),
        column4TextRenderer,
        MyTreeModel::Col_Column4,
        80,
        wxALIGN_LEFT,
        wxDATAVIEW_COL_RESIZABLE);
    pDataViewCtrl->AppendColumn(column4);


    /* ID Column */
    auto idColumn = new wxDataViewColumn(
        wxT("ID"), idColumnRenderer, MyTreeModel::Col_Id, 32, wxALIGN_CENTER, wxDATAVIEW_COL_HIDDEN);
    pDataViewCtrl->AppendColumn(idColumn);
}

class Application : public wxApp
{
public:
    Application();
    virtual ~Application() = default;

    bool OnInit() override;
};

Application::Application()
{
}

bool Application::OnInit()
{
    auto frame = new MainFrame();
    frame->Show(true);
    SetTopWindow(frame);

    return true;
}

wxIMPLEMENT_APP(Application);
Post Reply