How to make PropertyGrid Collection Items semi editable? - c#

I have a class called BasePath, which contains Drive, Path and MetaName properties.
Furthermore I have created a BasePathCollection to show them in the PropertyGrid (expandable).
For adding a path you have to click the "three dots button" where you get another PropertyGrid where you see all items of the "BasePathCollection" on the left and the items properties on the right.
When BasePath properties are [ReadOnly(true)] I can edit the path by clicking to another "three dots button":
But now I need to make the the MetaName property editable and boom, suddenly I can't edit the path. The "three dots button" is no longer accessible:
What do I need to change for getting the "three dots button" back with the ability to still edit the MetaName property?
Edit:
Declaration of Properties:
How is your MetaName property declared? Show us some code please. – Simon Mourier 1 hour ago
private string m_metaName;
[Browsable(true)]
[ReadOnly(true)]
public string Drive { get { return m_drive; } set { m_drive = value; } }
[Browsable(true)]
[ReadOnly(true)]
public string Path { get { Clear(); return m_path; } set { m_path = value; Clear(); } }
[Browsable(true)]
[ReadOnly(true)]
public string MetaName { get { return m_metaName; } set { m_metaName = value; } }
Yes in a lack of knowledge I tried to set the following attributes for the BasePath-Class to make it editable.
[TypeConverter(typeof(BasePathConverter))]
[Editor(typeof(FolderNameEditorWithRootFolder), typeof(System.Drawing.Design.UITypeEditor))]
public class BasePath : IComparable<BasePath>{ ... }

Related

how to show user class property at properties window in WPF

I'm trying to show user class property at properties window.
example, this is class code
public class GraphConstruct
{
private List<GC_VisualData> visualDataGroup = new List<GC_VisualData>();
[Browsable(true), Category("Option"), Description("graph option")]
public List<GC_VisualData> VisualDataGroup { get { return visualDataGroup; } set { visualDataGroup = value; } }
}
And UserControl contain this code
public GraphConstruct CONS = new GraphConstruct();
[Browsable(true), Category("graph option"), Description("graph option")]
public GraphConstruct GRAPH_CONSTRUCT { get { return CONS; } set { CONS = value; } }
And properties window showing to me like this.
I want to display my class property at properties window like string, enum, int.
Is it posible? If it possible where I start this work?
Please, give me keyword. I don't know how to search it.
have a nice day
I think you can only show the properties of the UserControl itself, which is shown in the properties window when the item is selected in the designer, not the properties of a property within the UserControl.
https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.browsableattribute?view=net-5.0
Edit: Dependency properties also show up in the properties window - https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/dependency-properties-overview?view=netframeworkdesktop-4.8#property-functionality-provided-by-a-dependency-property

Custom UserControl - Design-Time support for control repainting

I have created my custom UserControl with some custom properties for it. For example:
[Description("Example Description"),Category("CustomSettings"),DefaultValue("Transmedicom")]
public string DatabaseAddress
{
get; set;
}
Everything works fine. I can change custom property in code and in design-time.
What I'm looking for (and cannot find anything) now is: How could I repaint (reacreate) my UserControl in design-time when my custom property change in design-time.
Let's say when DatabaseName will be changed to localhost UserControl will add and display some Label on my UserControl. It's important to work in Design-Time.
Nothing special there. You just have to set the text to Label inside the property setter. That should update the UI.
private string databaseAddress;
[Description("Example Description"), Category("CustomSettings"), DefaultValue("Transmedicom")]
public string DatabaseAddress
{
get { return databaseAddress; }
set
{
databaseAddress = value;
yourLabel.Text = value;//Set value to Label or whatever
}
}
Try this
private string _databaseAddress = "localHost";
[Description("Example Description"), Category("CustomSettings"), DefaultValue("Transmedicom")]
public string DatabaseAddress
{
get
{
return _databaseAddress;
}
set
{
if(!string.IsNullOrEmpty(value))
{
_databaseAddress = value;
lblAddress.Text = value;
lblAddress.Invalidate();
}
}
}
Both previous answers are correct.
I just want to add that the user control can even react on resizing during design time, using the Layout event.

Generated a list of filenames, but no file paths

I have a list box that displays a set of filenames that reference text files. I think it is aesthetically unappealing to display full paths, so I used Path.GetFileName to cut off the directory part.
But now when the user selects a particular filename to open, I've lost the paths. The files could be located anywhere on the local computer (for now).
How can I use the list box so that I can display nice filenames, but also have reference to the actual file?
EDIT: I like the idea of having a custom wrapper class for each list box item.
What's I've done in the past is create a wrapper class for the objects I want to display in the ListBox. In this class override ToString to the string you want to display in the ListBox.
When you need to get details of a selected item, cast it to the wrapper class and pull the data you need.
Here's an ugly example:
class FileListBoxItem
{
public string FileFullname { get; set; }
public override string ToString() {
return Path.GetFileName(FileFullname);
}
}
Fill your ListBox with FileListBoxItems:
listBox1.Items.Add(new FileListBoxItem { FileFullname = #"c:\TestFolder\file1.txt" })
Get back the full name of a selected file like this:
var fileFullname = ((FileListBoxItem)listBox1.SelectedItem).FileFullname;
Edit
#user1154664 raises a good point in a comment to your original question: how would a user differentiate two ListBox items if the displayed file names are the same?
Here are two options:
Also display each FileListBoxItem's parent directory
To do this change the ToString override to this:
public override string ToString() {
var di = new DirectoryInfo(FileFullname);
return string.Format(#"...\{0}\{1}", di.Parent.Name, di.Name);
}
Display a FileListBoxItem's full path in a tooltip
To do this drop a ToolTip component on your form and add a MouseMove event handler for your ListBox to retrieve the FileFullname property value of the FileLIstBoxItem the user is hovering the mouse over.
private void listBox1_MouseMove(object sender, MouseEventArgs e) {
string caption = "";
int index = listBox1.IndexFromPoint(e.Location);
if ((index >= 0) && (index < listBox1.Items.Count)) {
caption = ((FileListBoxItem)listBox1.Items[index]).FileFullname;
}
toolTip1.SetToolTip(listBox1, caption);
}
Of course you can use this second option with the first.
Source for the ToolTip in a ListBox (the accepted answer, code reformatted to a flavor I prefer).
Use ListBoxItem.Tag to store the full path for each item if using WPF. Or, if using WinForms, you can create a custom class that stores the full path, but overrides object.ToString() so that only the filename is displayed.
class MyPathItem
{
public string Path { get; set; }
public override string ToString()
{
return System.IO.Path.GetFileName(Path);
}
}
...
foreach (var fullPath in GetFullPaths())
{
myListBox.Add(new MyPathItem { Path = fullPath });
}
I do this
public class ListOption
{
public ListOption(string text, string value)
{
Value = value;
Text = text;
}
public string Value { get; set; }
public string Text { get; set; }
}
Then create my list
List<ListOption> options = new List<ListOption>()
For each item in files
options.Add(new ListOption(item.Name, item.Value));
Next
bind my list
myListBox.ItemSource = options;
Then get my value or text
protected void List_SelectionChanged(...)
{
ListOption option = (ListOption) myListBox.SelectedItem;
doSomethingWith(option.Value);
}
Just the idea here is main thing
Personally I don't agree with you sentiment that this is ugly for the user. Showing the full path gives the explicit details to the user and enable them to have confidence in their selection or what ever they are doing.
I would use a Dictionary, using the item index as the Key and the full path of this list item as the value.
Dictionary<int, string> pathDict = new Dictionary<int, string>();
pathDict.Add(0, "C:\SomePath\SomeFileName.txt");
...
The above is probably the best way to go here over using the item.Tag property...
I hope this helps.

Update issue with data-bound Listbox and PropertyGrid

This is part of my AOI class (nothing special about it):
class AOI : INotifyPropertyChanged
{
private Guid _id;
private string _name;
private string _comment;
public Guid Id
{
get { return _id; }
}
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public string Comment
{
get { return _comment; }
set
{
_comment = value;
OnPropertyChanged("Comment");
}
}
public override string ToString()
{
if (_name.Length > 0)
{
return _name;
}
else
{
return _id.ToString();
}
}
}
I keep them in a BindingList<AOI> which is bound to a ListBox. In the SelectedValueChanged event of the ListBox I assign the selected object to a PropertyGrid, so that the user can modify the AOI.
This works fine except for the Name field (which is displayed in the ListBox (see ToString() above)).
When I edit the name field using the PropertyGrid, the ListBox is updated correctly. But in the PropertyGrid, the Name field (just the value) is cleared as soon as I press enter. The correct (modified) value appears when I set the cursor to another field in the PropertyGrid.
What is the easiest workaround to handle this correctly?
This is a problem of the PropertyGrid.
This can also be reproduced with the designer within the Visual Studio. Simply select a control and change its minimum size to a larger value than the current one. If you take a look into the grid, the value in the size property won't be updated till you select it within the grid.
If some rows won't update correctly normally one of these two options will help:
Reattach the object to the PropertyGrid by calling propertyGrid.SelectedObject = myObject
Force the grid to redraw itself by calling propertyGrid.Invalidate()

How can I create a control with IPAddress properties that can be edited in the designer?

I'm creating a control with properties of type System.Net.IPAddress. The designer shows these as read-only, and seems to be matching them up with resources. Is there a way to make it so that the user can edit these properties in the designer properties window, rather than having to open up the resource editor?
Found it - the answer is to fake it:
[Browsable(true)]
[DisplayName("IPAddress")]
public string IPAddressText
{
get { return this.IPAddress.ToString(); }
set { this.IPAddress = IPAddress.Parse(value); }
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IPAddress IPAddress
{
get;
set;
}

Categories