Property Combo items operation - add/remove/select

Grids for WPF Forum

Posted 11 years ago by Maulik Goradiya
Version: 4.5.0487
Avatar
Hi,

Please find below code to generate one property from Code Behind and Please give solution of following questions.

Requirement:
- Need to create it from Code Behind(Dynamically using propGrid.Properties.Add(...) method)
- Combo Box must contain key-value pair. Of which "Value" part is seen in combo box & key part will be used to indentify that combobox's item.
- need to add/remove item into/from combobox Dynamically.
- need to select perticular item by key or value part.

Q - 1: How can I change selection of combo-items on button click event? (ex. it defaults to "1" when loaded and I want to change it "3" when button is pressed.)

Q - 2: How can I remove/add item from/to combobox on button click event?

Code:
PropertyGridPropertyItem item = new PropertyGridPropertyItem();
item.DisplayName = "Combo Property";
item.Description = "Description of combobox type";
item.Category = "General Properties";

DataTemplate dataTemplate = new DataTemplate(); // DataTemple for Combo box
FrameworkElementFactory cmbBox = new FrameworkElementFactory(typeof(ComboBox));
cmbBox.Name = "myComboBox";
List<string> cb = new List<string>();
cb.Add("1");
cb.Add("2");
cb.Add("3");
cmbBox.SetValue(ComboBox.ItemsSourceProperty, cb); // Item source List<string>
cmbBox.SetValue(ComboBox.SelectedValueProperty, "1"); // Default value - 1
dataTemplate.VisualTree = cmbBox;
item.ValueTemplate = dataTemplate;
propGrid.Properties.Add(item as IPropertyDataAccessor); // Add it.

// Test Button Click event handler
private void btnTest_Click(object sender, RoutedEventArgs e)
{
// 0 index item
PropertyGridPropertyItem item = (PropertyGridPropertyItem)propGrid.Properties[0];
if (item != null)
{
FrameworkElementFactory cmbBox = item.ValueTemplate.VisualTree;
//Error:After a 'FrameworkElementFactory' is in use(sealed), it cannot be modified.
cmbBox.SetValue(ComboBox.SelectedItemProperty, 0);
}
}

Comments (6)

Posted 11 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Maulik,

You shouldn't need to access the ComboBox directly. The PropertyGridPropertyItem has a Value property, which should be bound to the SelectedItem of the ComboBox and the object you access in your click handler.

In the code below, I set the item.Value and bind the ComboBox.SelectedItem to it. Then you can modify the item.Value property and it will be reflected in the ComboBox (and vice versa).
public Window1() {
    InitializeComponent();

    PropertyGridPropertyItem item = new PropertyGridPropertyItem();
    item.DisplayName = "Combo Property";
    item.Description = "Description of combobox type";
    item.Category = "General Properties";
    item.Value = "1";

    DataTemplate dataTemplate = new DataTemplate(); // DataTemple for Combo box 
    FrameworkElementFactory cmbBox = new FrameworkElementFactory(typeof(ComboBox));
    cmbBox.Name = "myComboBox";
    List<string> cb = new List<string>();
    cb.Add("1");
    cb.Add("2");
    cb.Add("3");
    cmbBox.SetValue(ComboBox.ItemsSourceProperty, cb); // Item source List<string> 
    cmbBox.SetBinding(ComboBox.SelectedItemProperty, new Binding("Value") { RelativeSource = new RelativeSource() { AncestorType = typeof(IPropertyDataAccessor) } });
    dataTemplate.VisualTree = cmbBox;
    item.ValueTemplate = dataTemplate;
    this.propertyGrid1.Properties.Add(item); // Add it. 
}

private void button1_Click(object sender, RoutedEventArgs e) {
    // 0 index item 
    PropertyGridPropertyItem item = (PropertyGridPropertyItem)this.propertyGrid1.Properties[0];
    if (item != null)
        item.Value = "1";
}


Actipro Software Support

Posted 10 years ago by Balaram Barange
Avatar
As per the above threads, I want to know how to add extra items on that combobox OR remove items from it?

I have made little changes on your code, but I have to write PropertyGrid1.Refresh line. How can I achive this without calling refresh method which flickers entire screen?

public Window1() {
....
    List<string> cb = new List<string>();
    cb.Add("1");
    cb.Add("2");
    cb.Add("3");
    cmbBox.SetValue(ComboBox.ItemsSourceProperty, cb); // Item source List<string> 
    cmbBox.SetBinding(ComboBox.SelectedItemProperty, new Binding("Value") { RelativeSource = new RelativeSource() { AncestorType = typeof(IPropertyDataAccessor) } });
    dataTemplate.VisualTree = cmbBox;
    item.ValueTemplate = dataTemplate;

    item.Tag = cb; // My Line

    this.propertyGrid1.Properties.Add(item); // Add it. 
}

private void button1_Click(object sender, RoutedEventArgs e) {
    // 0 index item 
    PropertyGridPropertyItem item = (PropertyGridPropertyItem)this.propertyGrid1.Properties[0];
    if (item != null)
    {
        item.Value = "1";
        ((List<string>)item .Tag).Add("4"); // My Line
        this.propertyGrid1.Refresh(); // I have to write this line which flickers entire screen Can you please suggest alternate way?
    }
}
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Balaram,

If you want to be able to add/remove values dynamically, then you need to bind the ComboBox.ItemsSource to a property that is accessible from your Window (or where ever you want to update the items from). So you would need to:

1. Create a non-dependency property (with a get accessor only) on the Window class of type ObservableCollection<string>, say MyComboBoxItems
2. Create a backer field for the property, that is initialized in the Window constructor, and is returned from the property in #1.
3. Bind the ComboBox.ItemsSource property to the MyComboBoxItems.

Then any changes you make to the MyComboBoxItems collection will be reflected in the ComboBox.


Actipro Software Support

Posted 10 years ago by Balaram Barange
Avatar
Hi Actipro Software Support Team,

Thank you very much for the support. We got the desired effect.
Posted 10 years ago by Nate Smith - Software Engineer, Logical Progression Group
Avatar
I have this exact situation but I guess I am missing something about how to implement this. I have a class called 'Form' that has a 'ClassName' property that is a string, and an 'AvailableClasses' property that is ObservableCollection<string> and both fire the INotifyPropertyChanged PropertyChanged event when modified (if that matters). My custom editor is:

public class AvailableClassNamesEditor : PropertyEditor
    {
        public AvailableClassNamesEditor()
        {
            DataTemplate dataTemplate = new DataTemplate();
            FrameworkElementFactory combo = new FrameworkElementFactory(typeof(ComboBox));

            combo.SetBinding(ComboBox.ItemsSourceProperty, new Binding("AvailableClasses") { RelativeSource = new RelativeSource() { AncestorType = typeof(IPropertyDataAccessor) } });
            combo.SetBinding(ComboBox.SelectedItemProperty, new Binding("ClassName") { RelativeSource = new RelativeSource() { AncestorType = typeof(IPropertyDataAccessor) } });

            // also does not work
            //combo.SetBinding(ComboBox.ItemsSourceProperty, new Binding("AvailableClasses"));
            //combo.SetBinding(ComboBox.SelectedItemProperty, new Binding("ClassName"));


            dataTemplate.VisualTree = combo;
            this.ValueTemplate = dataTemplate;            
        }
    }
But the binding code isn't correct. The type of object in the SelectObject property is the Form but, of course, the object that the binding is attempting to bind to is a PropertyGridDataAccessorItem. When I simply provide the property name without the RelativeSource (as shown in the commented lines) I get no binding error, but it still doesn't work. Any ideas what I'm missing?

[Modified at 03/23/2010 03:49 PM]

[Modified at 03/23/2010 03:49 PM]
Posted 10 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Nate,

If you are just setting PropertyGrid.SelectedObject to an instance of your 'Form' (and 'Form' isn't in the visual tree), then that binding won't work. You would need to ensure that your 'Form' type is a parent Visual of the PropertyGrid, for the RelativeSource with AncestorType to work.

This post describes a way to access the target object's properties, which may be useful for you.

If none of this helps, can you please put together a small sample project and email it over to our support address? Once we have that we can take a closer look.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.