I have a app that makes use of the PropertyGrid in C#/.NET
the PropertGrid holds onto the MyAppObject class/object shown below..
class MyAppObject
{
private List<MyObject> oItems;
public List<MyObject> Items
{
get { return this.oItems; }
}
}
And so far it works well, nice and simple. I want the property grid to allow users to view the items, which it does well, however when you select the property in the PropertyGrid the dialog also allows to add more List<MyObject> items.
I do not want this, I only want to have the ability to show the items, not edit them.
I thought by not providing the setter (set { this.oItems = value; }):
then it wouldnt allow the add button.
Hope this makes sense, The screenshots shows the dialog, and I circled the buttons I want to remove.
thanks
If you expose it as a read-only list, it should do what you need:
[Browsable(false)]
public List<MyObject> Items
{
get { return this.oItems; }
}
// this (below) is the one the PropertyGrid will use
[DisplayName("Items")]
public ReadOnlyCollection<MyObject> ReadOnlyItems
{
get { return this.oItems.AsReadOnly(); }
}
Note that the members of individual objects (MyObject instances) will still be editable, unless you decorate them as [ReadOnly(true)].
As you note, the setter is not necessary to add/remove/edit items. That is because the grid still has full access to the .Add, .Remove and indexer (list[index]) operations.
This is a slightly tricky one; the solution involves building with the full .NET Framework (since the client-only framework doesn't include System.Design). You need to create your own subclass of CollectionEditor and tell it what to do with the temporary collection after the UI is finished with it:
public class MyObjectEditor : CollectionEditor {
public MyObjectEditor(Type type) : base(type) { }
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
return ((MyObject)context.Instance).Items;
}
}
Then you have to decorate your property with the EditorAttribute:
[Editor(typeof(MyObjectEditor), typeof(UITypeEditor))]
public List<MyObject> Items{
// ...
}
Reference: What's the correct way to edit a collection in a property grid
Alternative:
return new ReadOnlyCollection(oItems);
OR
return oItems.AsReadOnly();
Related
I have a class with some properties and methods and I bind an ObservableCollection of objects of this class to a list view in a Windows Universal App.
However a lot of the things I want to display on each item of this list are properties of the class which are derived from other properties: for example I might have a Boolean about the object and then for the UI two colours representing true and false. This Boolean may may also the result of calculations between multiple float properties of the object
My question is can I bind the result of a method in the class to save me from calculating the other properties separately and having properties for those things?
I've looked into converters but they look like they operate on a single property and here I need to be able to act on multiple properties
Assuming you have this
public class MyClass
{
public bool MyBool {get; set;}
public Color MyColor()
{
if (this.MyBool) return Colors.Green;
else return Colors.Red;
}
}
And you want to bind MyColor, you could just make it a readonly property.
public class MyClass
{
public bool MyBool {get; set;}
public Color MyBoolColor { get { return this.MyBool ? Colors.Green : Colors.Red; }
}
You then proceed to bind and use MyBoolColor as you wish. Basically, what you now have as methods beceome the get part of read-only properties.
This is of course a very short proof-of-concept which might need to be adapted to your actual code.
I have a List object that I need to be able to swap the object type dynamically. Basically I have:
List<DataBaseItems> items = new List<DataBaseItems>();
I will then perform some filtering on that list with LINQ then bind to a telerik grid. I need to swap out the object based on an id that i get. My goal is to build a custom control that can use it's filter button for multiple reports where the report data is coming from the above list. Report A may use the above list and report B needs a completely different object but has the same actions on it.
Create an interface and implement it into whatever objects you implement.
public interface ICustomListFilter<T>
where T:class
{
public void FilterAndBindMyList(List<T> myList);
}
public class ReportOneFilter:ICustomListFilter<MyFirstType>
{
public void FilterAndBindMyList(List<MyFirstType> items)
{
// your filtering and binding code goes here, such as items.Where(i => ...
}
}
public class ReportTwoFilter:ICustomListFilter<MySecondType>
{
public void FilterAndBindMyList(List<MySecondType> items)
{
// your another filtering and binding algorithm goes here, such as items.Select(i => ...
}
}
I've done a lot of samples but nowhere encountered on my problem.
Namely, I would like to create a Grouped GridView, which consists of two groups, with the exception that each group is made up of completely different collection. For example, I would like to in the first group were Animals, and in the second, Cars.
I would also like to each of these groups had a different Template ;)
Make both your inner collection items derive from a common base class. When I did this I had an ItemBase class, and my Event, Story, and Party classes all derived from Item base.
Then, my groups collection items each contained a definition for Items of ObservableCollection. (I guess, thinking about it now, I could have used object as the implied base type, but I didn't) When coded this was actually populated with my derived classes, e.g.
Items.Add(new Event { Title = "I am an event" };
When you display the items in your grid, you will want to create a new class that derives from ItemTemplateSelector, and override the SelectTemplateCore(object item, DependencyObject container) method. My logic was as simple as
if(item is Event) { return EventTemplate; }
else if(item is Story) { return StoryTemplate }
else { return DefaultTemplate; }
(My Party item used the default template.)
Create a ObservableCollection and push your collection items.
Like This:
public class ScreenGroupModel
{
private ObservableCollection<object> _groupItems = new ObservableCollection<object>();
public ObservableCollection<object> GroupItems
{
get { return this._groupItems; }
}
public ScreenGroupModel()
{
}
public ObservableCollection<object> GetScreenGroups()
{
_groupItems.Add(new Class1);
_groupItems.Add(new Class2);
return _groupItems;
}
}
This Sample, simple collection showing. You can be used DataTemplateSelectors. Every kind of class, select a template.
ObservableCollection -> "object" type is important. Because, object is base type. You can be add, every kind class.
Regards ;)
When I add an item to the CheckedListBox list box I also want to store a reference to another object. I tried adding a new instance of this object to the CheckedListBox.
public class CheckedListBoxExtention : CheckedListBox
{
private ReferenceItem _referenceItem;
public ReferenceItem storedItem
{
get { return _referenceItem; }
set { _referenceItem = value; }
}
public CheckedListBoxExtention(ReferenceItem storedItem)
{
_referenceItem = storedItem;
}
}
This works in that later when I foreach though the items in CheckedListBox I have a reference to the _referenceItem object. However, when I add items like this, CheckedListBox shows up as blank (the list in the GUI itself). So I am trying to find a way to override the item text or something like that.
This is the code I used to fix the problem
class ReferenceItemWrapper
{
private ReferenceItem _item;
public ReferenceItemWrapper(ReferenceItem item)
{
_item = item;
}
public ReferenceItem getItem
{get {return _item;}}
public override string ToString()
{
return _item.ToString();
}
}
I am a bit new to wrappers. Why exactly did it work after it was wrapped when it did not work when I added the ReferenceItem directly to the CheckedListBox?
The CheckedListBox uses the ToString method of the objects in the list to populate the captions in the box. Rather than extend the CheckedListBox, just create a wrapper class that lets you store both your reference and a caption, and implements a ToString method which returns your caption. Just create one of your wrapper objects, stick the text in it, stick your reference in it, then add the wrapper object to the list box.
As you can see in the pic below, for a ListView Control you can add Items using the Properties pane.
How do I enable this kind of stuff for my UserControl?
I'm not getting anything when I search Google, but I'm probably not using the correct terms.
Does anybody know?
Thanks
You need to create a class that defines the object type that the collection ids composed of. A listView has ListViewItem objects. A TabControl has TabPage objects. Your control has objects which are defined by you. Let's call it MyItemType.
You also need a wraper class for the collection. A simple implementation is shown below.
public class MyItemTypeCollection : CollectionBase
{
public MyItemType this[int Index]
{
get
{
return (MyItemType)List[Index];
}
}
public bool Contains(MyItemType itemType)
{
return List.Contains(itemType);
}
public int Add(MyItemType itemType)
{
return List.Add(itemType);
}
public void Remove(MyItemType itemType)
{
List.Remove(itemType);
}
public void Insert(int index, MyItemType itemType)
{
List.Insert(index, itemType);
}
public int IndexOf(MyItemType itemType)
{
return List.IndexOf(itemType);
}
}
Finally you need to add a member variable for the collection to your user control and decorate it properly:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public MyItemTypeCollection MyItemTypes
{
get { return _myItemTypeCollection; }
}
and you now have a simple interface that allows you to browse and edit the collection. Leaves a lot to be desired still but to do more you will have to learn about custom designers which can be difficult to understand and implement.