I derived a class from CMFCPropertyGridCtrl to add a simple interface for my needs. I want to add a new string value so I can edit it:
void CPropertyGrid::AddString(const char* tag, const char* defaultValue)
{
COleVariant valueType(defaultValue);
CMFCPropertyGridProperty *stringProperty = new CMFCPropertyGridProperty(tag, valueType);
stringProperty->AllowEdit(TRUE);
AddProperty(stringProperty);
}
This adds a new string in the property grid, but I can't edit it. Is there another way to make this editable?
Thanks!
Notify value must be set to true to be able to edit values
Related
I have a list of application specific items uniquely identified by an id. Their names are displayed in a QTreeWidget (one item corresponds to a single QTreeWidgetItem). I would like to somehow attach the corresponding ids to these QTreeWidgetItems so that upon selection changed I can access the id of the corresponding item and do some processing.
QTreeWidgetItem does not inherit from QObject so I cannot use its setProperty function. How could I do this?
Just create some user defined roles for the properties...
typedef enum {
id_1_role = Qt::UserRole,
id_2_role,
id_N_role,
} property_id_role;
Then you can use the normal means of getting/setting the data associated with a QTreeWidgetItem.
QTreeWidgetItem *item = ...
/*
* Set the property value.
*/
item->setData(column, property_id_role::id_2_role, id_2_value);
/*
* Get the property value.
*/
auto id_2_value = item->data(column, property_id_role::id_2_role).value<id_2_type>();
Do you know that QTreeWidgetItem has a setData method?
setData(int column, int role, const QVariant &value)
You can use it with your roles. For example:
int your_id = 123;
ui->treeWidget->currentItem()->setData(0,Qt::UserRole,your_id);
qDebug() << ui->treeWidget->currentItem()->data(0,Qt::UserRole);
From various questions, I know it is impossible to create DataTemplate from the code behind without using the XamlReader. So I want to ask if there is a way to programatically generates the UI for each Item in a ListView. I don't seem to find any relevant event handler or member of ListView for this purpose. Ideally, I want the ListView to invoke my handler code to generate UI for each data item it needs to display.
Imitating the official XamlTreeView sample, I have tried overriding some ListView method such as PrepareContainerForItemOverride but this won't work. The solution I found is as #JustinXL suggests: producing ListViewItem and insert them to the ListView->Items directly
//assume that items is a list of items we want to bind
myListView->Items->Clear();
for(auto i : items)
{
ListViewItem^ v = ref new ListViewItem();
v->Content = GenerateUIFor(i);
myListView->Items->Append(v); // NOTE: a wrapping ListViewItem is required!
}
To support usual data binding, it would be best to make the data structure to cache the generated UI. For example,
ref class MyDataStructure
{
public:
property ListViewItem^ Item
{
ListViewItem^ get()
{
if (_item == nullptr)
GenerateUI();
return _item;
}
}
void GenerateUI()
{
_item = ref new ListViewItem();
_text_block = ref new TextBlock(); // sample
_item->Content = _text_block;
UpdateUI();
}
// Invoke this when changing the state of this object
void UpdateUI()
{
if (_text_block != nullptr) // sample
{
_text_block->Text = this->ToString(); // sample
}
}
private:
ListViewItem^ _item;
TextBlock^ _text_block;
};
The downside of this is of course we can't make use of data virtualization. But it works properly for small set of data. For large set, one can use website's approach with Next and Prev button to load next page or go back to previous page.
ItemContainerGenerator should let you construct the entire UI for an item inside a list view. Unfortunately there doesn't appear to be much in the way of non MSDN documentation/samples for this.
Alternatively if you can maintain a list of all the DataTemplates you might need to show, you could use a DataTemplateSelector to choose which DataTemplate you want to show for each individual item.
I'm doing my controller. When I click on an item in my ListWidget, the following method is called :
void ContactBookController::setCurrentlySelectedItem(QListWidgetItem *item)
{
setCurrentItem(*item);
m_window.setEditButtonsState(true);
}
And the setCurrentItem() method is as follows : (m_current_item is a private variable):
void ContactBookController::setCurrentItem(const QListWidgetItem ¤t_item)
{
m_current_item = current_item;
}
Now, when I create a contact, I add an item to the QListWidget, but I also create a Contact object, but I also bind them together in a QHash so I know what QListWidgetItem corresponds to what Contact. In short, here is what I did :
void ContactBookController::createContact()
{
auto new_contact = m_contact_book.createContact();
if(new_contact != nullptr)
{
new_contact->setName(tr("New contact"));
}
auto list_item = m_window.createContact(new_contact->getName());
m_window.clearSelection();
m_contact_map.insert(list_item, new_contact);
}
Now, when clicking on a QListWidgetItem, I activate the edit button and I would like to retrieve the corresponding Contact object. However, when doing this, the Contact object doesn't seem to be correct. Indeed, if I use a method on him (like getName()), my application instantly crashes.
Here is what I did :
void ContactBookController::editContact()
{
auto list_item = m_current_item;
auto contact = m_contact_map.value(&list_item); /* doesn't work */
}
My hash table is declared as such :
QHash<QListWidgetItem*, Contact*> m_contact_map;
Any idea what I did wrong ?
Your hash has the type QHash<QListWidgetItem*, Contact>. So, mapping a item pointer to a contact value.
When you save the mapping for a specific item with m_contact_map.insert(list_item, new_contact), you add a mapping from the item pointer to the contact. But when you try to retrieve the contact with m_contact_map.value(&list_item), you look up the value for the pointer to the local list_item variable, which points to somewhere on the stack, and has nothing to do with the pointer to the item that is shown in the view.
Either you need to save to pointer to the selected value, i.e. make m_current_item a QListWidgetItem *m_current_item, or you simply use QListWidget::currentItem() to retrieve the current item without the need for an additional member variable.
(Side note: You should check for currentItem() != nullptr, since a list widget does not necessarily has an item selected.)
I create my own class:
class myTile : public QGraphicsItem{}
I add these myTile in a QGraphicsScene. Every myTile has a value and a getter for the value. Now I want to get a myTile and read its value.
I tried collidingItems() and itemAt(), but the problem is: These two method can only return QGraphicsItem. The QGraphicsItem doesn't have my return value method in myTile. Is there a way to get a custom item?
Thank you in advance!
myTile *t = (myTile*)myScene->itemAt(i);
t->myMethod();
I've done this before with a web control, but I can't seem to get it to work with a sublayout. On the Presentation Details for a particular item I'm assigning my Sublayout and then in the additional parameters section specifying the parameter. Here's the code that's in the code-behind for my sublayout. When I run the debugger, RenderPageTitle is just null.
public partial class PageContent : System.Web.UI.UserControl
{
public String RenderPageTitle { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (RenderPageTitle.ToLower().Equals("false"))
{
TitleFieldRenderer.Visible = false;
}
}
}
please refer to this blog post.
For sitecore6, in the .cs file:
string rawParameters = this.Parameters;
NameValueCollection parameters = Sitecore.Web.WebUtil.ParseUrlParameters(rawParameters);
or in .ascx file:
string rawParameters = Attributes["sc_parameters"];
NameValueCollection parameters = Sitecore.Web.WebUtil.ParseUrlParameters(rawParameters);
There may be some better way to do this. It's hard to say.
The parameters to a sublayout are URL encoded (HttpUtility.UrlEncode or similar) and joined together like a querystring, and then placed in the "sc_parameters" attribute of the control.
So, like chiesa said, in a web user control (this is what that blog meant by .ascx file) you can do this:
string rawParameters = Attributes["sc_parameters"];
NameValueCollection parameters =
Sitecore.Web.WebUtil.ParseUrlParameters(rawParameters);
And then you have the parameters as a dictionary of strings. However, these are still encoded, so if they contain anything other than letters and numbers you will probably want to use something like HttpUtility.UrlDecode to fix them.
string color_scheme = HttpUtility.UrlDecode(parameters["ColorScheme"]);
int ash_diffuser_id = // Could have a + sign prepended or something.
HttpUtility.UrlDecode(Int32.Parse(parameters["AshDiffuserID"]));
You can have sublayout 's parameter value by declaring _Param variable with NameValueCollection data type and refer tem to get the specific parameter value by passing the key value . This way this common function can reside into helper file and can be reused .
Here is the code snippet.
// All known parameters passed to the sublayout.
static NameValueCollection _params = null;
/// <summary>
/// Return the value of a specific parameter.
/// </summary>
/// <param name="key">Parameter name.</param>
/// <returns>Value of specified parameter.</returns>
public static string GetParam(string key)
{
key.Trim().ToLower();
string result = _params[key.Trim().ToLower()];
if (String.IsNullOrEmpty(result))
{
result = String.Empty;
}
return (System.Web.HttpUtility.UrlDecode(result));
}
You can get the value of the parameter that you passed in the sublayout simply by passing the key name of the parameter as an argument of this function .
Hope this helps .