Custom Enum Dropdown

25 posts, 1 answers
  1. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 10 Apr 2013 Link to this post

    Is there a way to customize the Enum dropdown list for a field?  We have different permission settings for our applications, and we have to limit options for some users.  An Example would be to have the following code:

    Enum Produce
    Apples
    Oranges
    Pears
    Peaches
    End Enum

    Where we can set the 'Produce' field for some users to be able to see and select Apples and Oranges only, while others can  see and select the full list.

    I have been directed to this article: http://www.telerik.com/help/wpf/radcombobox-howto-enable-disable-radcombobox-items.html, but that deals with setting it up with Xaml.  I need to change the list on the fly at runtime, and have accessed the RadComboBox with this line of code:

    ComboBoxItems = RadPropertyGrid1.ChildrenOfType(Of RadComboBox)()

    But now that I have it, how can I manipulate the list?  I have autobinding on, so when I try to clear or set the items manually, I get the error:

    "Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead."

  2. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 11 Apr 2013 Link to this post

    Hello Andrew,

    I would recommend you to run through this forum thread and the sample attached there. Although it is for RadGridView, the idea and implementation should be equal. 

    Kind regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. UI for WPF is Visual Studio 2017 Ready
  4. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 11 Apr 2013 Link to this post

    Hello Maya,

    I combed through both examples in the thread, and it appears that it is too different from what I want to do.  That example dealt with manually binding elements (autogenerate = "false") and used a list of instanced objects.  I'm trying to hide Enum values (that were autogenerated) without messing too much with the binding of the original property.

    Basically, I want to autogenerateproperty, go into at runtime and manipulate the default Enum of a radcombobox by removing/hiding some of the dropdown items.


  5. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 16 Apr 2013 Link to this post

    Hello Andrew, 

    I might be missing something, but in the first project attached in the forum thread, the whole logic is handled with binding to a property "IsFree" and the items in the combo are autogenerated. Could you clarify why this approach is not suitable for your scenario ?
    Furthermore, how do you bind the property grid and change its Item ? Would it not be possible to update the source for the combo box while changing the item ? 

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  6. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 16 Apr 2013 Link to this post

    The difference is the isFree property is bound to a list of objects, rather than an Enumeration type.  I've tried building a list of enumeration values, but the dropdown was blank, although it had the correct number of slots (Say I have a list of 2 enumeration values, there were 2 blank choices in the dropdown.)
  7. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 16 Apr 2013 Link to this post

    To further explain, I put together the following code, modifying the first example in that forum thread.

    In this, I have a business class with an enumeration of Produce with Fruit, Vegetables, Meat, Dairy and Grains as options.  I have defined a list with only dairy, grains, and Vegetables.  And try to set the radcombobox.itemsource = limitedlist.  It shows the right number of options, but the text fields are blank.

    <Window x:Class="MainWindow"
            Title="MainWindow" Height="350" Width="525">
            <Grid>
            <telerik:RadPropertyGrid Margin="0,37,0,0" Name="RadPropertyGrid1" />
            <TextBox Height="23" HorizontalAlignment="Left" Margin="96,6,0,0" Name="tStoreName" VerticalAlignment="Top" Width="252" />
            <Label Content="My Store Name" Height="28" HorizontalAlignment="Left" Margin="0,6,0,0" Name="Label1" VerticalAlignment="Top" />
        </Grid>
    </Window>

    Imports System.Reflection
    Imports Telerik.Windows.Controls.Data.PropertyGrid
    Class MainWindow
        Public MyStore As New GroceryStore
        Public LimitedProduceList As New List(Of GroceryStore.ProduceTypes)
     
        Public Sub New()
     
            ' This call is required by the designer.
            InitializeComponent()
     
            ' Add any initialization after the InitializeComponent() call.
            Me.RadPropertyGrid1.Item = MyStore
     
            LimitedProduceList.Add(GroceryStore.ProduceTypes.Dairy)
            LimitedProduceList.Add(GroceryStore.ProduceTypes.Grains)
            LimitedProduceList.Add(GroceryStore.ProduceTypes.Vegetables)
     
        End Sub
     
        Private Sub RadPropertyGrid1_FieldLoaded(sender As System.Object, e As Telerik.Windows.Controls.Data.PropertyGrid.FieldEventArgs) Handles RadPropertyGrid1.FieldLoaded
            'warning!  You can't update visibilities here.  The internal field control cannot handle the refresh until all field loaded events are called.
            Dim MyRadComboBox As RadComboBox = Nothing
            Try
                Dim requiredPropertyDefinition = Me.RadPropertyGrid1.PropertyDefinitions.FirstOrDefault(Function(p) p.DisplayName = "MainProduce")
                Dim propertyGridField = Me.RadPropertyGrid1.ChildrenOfType(Of PropertyGridField)().FirstOrDefault(Function(t) t.DataContext Is requiredPropertyDefinition)
                MyRadComboBox = TryCast(propertyGridField.Content, RadComboBox)
     
                MyRadComboBox.ItemsSource = LimitedProduceList
     
            Catch ex As Exception
            End Try
        End Sub
     
    End Class
     
    Public Class GroceryStore
        Public Property Name As String
        Public Property MainProduce As ProduceTypes
     
        Public Enum ProduceTypes As Long
            Fruit
            Vegetables
            Meat
            Dairy
            Grains
        End Enum
     
    End Class

  8. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 17 Apr 2013 Link to this post

    Hi Andrew,

    Such behavior can be observed when combo box cannot display the value from the source. Can you try setting DisplayMemberPath property and verify whether it is visualized properly ?  

    Greetings,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  9. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 17 Apr 2013 Link to this post

    Maya,

    I'm not familiar with setting the DisplayMemberPath property.  Nor do I understand what you mean by if it is visualized properly.  I checked the DisplayMemberPath and it's set to "DisplayName" by default.  I tried changing it, and nothing changed, but I really don't know what to set the value to.

    The main error I can see is that I'm attaching a list of Enumeration values to a radcombobox, which is binded to a property with a type of just a single enumeration value. (not a list).


    I appreciate your help to this point, but I'm still not sure we're trying addressing the same issue.  Just to recap, I'm trying to get a property (Produce) of type (ProduceType), which is defined as an enumeration (with values 'Fruit', 'Vegetables', 'Meat', 'Dairy' and 'Grains') to display only a select portion of the enumeration values in the dropdown(only 'meat' and 'dairy'), even though the property is autogenerated and bound to the property (Produce). 

    In the example I provided, I doubt the method I used is ideal for what I want to do.  It's just my best guess on how it can be done. 

    Thanks!
    Andrew

  10. Answer
    Maya
    Admin
    Maya avatar
    4062 posts

    Posted 19 Apr 2013 Link to this post

    Hello Andrew,

    I am attaching a project that might illustrate a similar scenario to yours. Could you take a look at it and update it so that it meets your exact requirements and let me know how to modify it on my side ? 

    Greetings,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  11. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 19 Apr 2013 Link to this post

    Maya,

    Thanks! That seems to do the trick.  I had a problem opening the project, as it wasn't compatible with my version of visual studio (2010).  But I was able to extract the code, and run it.  The key appears to be in either redefining the PropertyDefinition as a lookupPropertyDefinition, and resetting the binding and itemsource at the same time.

    Sample VB code:
    For n As Integer = 1 To Me.RadPropertyGrid1.PropertyDefinitions.Count
               If RadPropertyGrid1.PropertyDefinitions(n - 1).DisplayName = "MainProduce" Then
                   RadPropertyGrid1.PropertyDefinitions(n - 1) = New LookupPropertyDefinition With { _
                       .Binding = New Binding("MainProduce"),
                       .ItemsSource = New List(Of GroceryStore.ProduceTypes)() From {GroceryStore.ProduceTypes.Dairy, GroceryStore.ProduceTypes.Grains}}
     
               End If
           Next
  12. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 22 Apr 2013 Link to this post

    There appears to be a glitch with LookupPropertyDefinitions not clearing when the propertygrid item is disposed and reset:

    Propertygrid1.item = nothing
    Propertygrid1.item = new Item

    If I run the above code, all lookuppropertydefinitions are retained, while regular propertydefinitions are cleared and reset.

    I need to manually call out:

    Propertygrid1.item = nothing
    Propertygrid1.PropertyDefinitions.clear()
    Propertygrid1.item = new Item

    It's not a problem now that I have it fixed, but it may cause other issues I'm not aware of.
  13. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 24 Apr 2013 Link to this post

    Hello Andrew,

    Actually, that would be a kind of an expected behavior. When AutogeneratePropertyDefinition is true and the item is changed, we clear only those properties whose IsAutogenerated property is true. This is not the case with the lookup property definition since it is manually created in the event.
    The approach with clearing the PropertyDefinitions is appropriate or you can try to remove just the lookup property definition, property grid will take care of the rest. Another hint would be not to set the Item to null. There is actually no need for doing this, just changing the item property should do the job.
    Let me know in case you have further problems. 

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  14. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 30 Apr 2013 Link to this post

    Okay, so this solution works for simple dropdowns.  But no longer allows for multiple selection (flag enums)  Is there a way to do this while keeping flag enums?
  15. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 30 Apr 2013 Link to this post

    Hello Andrew,

    Could you clarify a bit - what is not working in this case ?  

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  16. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 30 Apr 2013 Link to this post

    By implementing the solution from your example, I'm adding a list of Enum values to the field.  This is fine for a standard Enum.  But when I want implement an Enum with the Flags attribute, so I can select multiple values, this doesn't appear to work in the example, and I'm not sure how to work around it.
  17. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 30 Apr 2013 Link to this post

    Hi Andrew,

    I mgiht be missing something here, but do you expect to have a flag enum editor as illustrated in this article ? If so, you can try following the approach explained there by createing editor template for a particular property definition.   

    Greetings,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  18. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 30 Apr 2013 Link to this post

    Yes,

    That's my intention.  But while specifying custom lists by adding a LookupPropertyDefinition at runtime.  So you're saying I can add an editor template here, and it should work?

    For n As Integer = 1 To Me.RadPropertyGrid1.PropertyDefinitions.Count
               If RadPropertyGrid1.PropertyDefinitions(n - 1).DisplayName = "MainProduce" Then
                   RadPropertyGrid1.PropertyDefinitions(n - 1) = New LookupPropertyDefinition With { _
                       .Binding = New Binding("MainProduce"),
                       .ItemsSource = New List(Of GroceryStore.ProduceTypes)() From {GroceryStore.ProduceTypes.Dairy, GroceryStore.ProduceTypes.Grains}}
      
               End If
           Next

    That would lead me to my next question.  I'm not yet comfortable with Xaml, or C#, and have yet to find an adequate example that clearly indicates how I can mix and match editor templates at runtime.  I've found work-arounds modifying the FieldInfo directly (extracting the textboxes, radcomboboxes, etc and modifying them in codebehind) to get what I need, and the results so far are satisfactory.  So if I need to set the editor template to a flag enum template at runtime, how would i do that using the above code as a reference?
  19. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 30 Apr 2013 Link to this post

    Hello Adnrew,

    If you create a DataTemplate in the Resources and give it a key, they you can assign the EditorTemplate property of the property definitions in a way similar to:
    myPropertyDefinition.EditorTemplate = (DataTemplate)this.Resources["MyEditorTemplate"];

    All the best,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  20. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 01 May 2013 Link to this post

    Maya,

    Can you let me know what I'm doing wrong? I define the template here.  Then call the code you provided in the background, and it returns a value of null.

    <Grid.Resources>
        <DataTemplate x:Key="MyFlagEnumTemplate">
            <telerik:FlagEnumEditor  >
            </telerik:FlagEnumEditor>
        </DataTemplate>
    </Grid.Resources>
  21. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 01 May 2013 Link to this post

    Maya, 

    My apologies, my last question comes because I'm still learning Xaml, I put the template in grid.resources when I needed to put it in window.resources.  I have a FlagEnumEditor returned now, but it doesn't appear to allow me to select anything.  I'm redefining the property definition as follows, where the new item source is a list of enum values (in this case, a list of flagged Enum values).  When I run this code the editor is blank, and has no items.

    RadPropertyGrid1.PropertyDefinitions.Insert(n - 1, new LookupPropertyDefinition {
        Binding = new Binding(PropertyName),
        ItemsSource = TowerDefinition.GetPropertyList(ListID),
        GroupName = GroupName,
        Description = Description,
        OrderIndex = OrderIndex,
        DisplayName = DisplayName,
        Visibility = Visibility,
        EditorTemplate = (DataTemplate)this.Resources("MyFlagEnumTemplate")
    })
  22. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 01 May 2013 Link to this post

    Hello Andrew,

    Actually, if you define Key attribute for the Grid, you can work with its Resources as well. So, if the key is "MyGrid", you can find it as: this.MyGrid.Resources[...].
    As for the current problem, you need to create regular PropertyDefinition (no need to to have LookupPropertyDefinition, since you will place FlagEnumEditor as an editor). You have to set the source to the FlagEnumeEditor, rather then the property definition. 

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  23. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 01 May 2013 Link to this post

    Maya,

    Can you clarify what you mean by setting the source to the FlagEnumEditor, rather then the property definition? Did you mean Itemsource?  I wasn't setting the source on this (and admittedly, It was coming back null, which was confusing).  

    Does the LookupPropertyDefinition have auto-define it's source, that's independent of it's binding?

    Will your approach work for a property that is defined as a single Enum, and yet have a custom source list of items?

  24. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 03 May 2013 Link to this post

    Hi Andrew,

    Could you please take a look at the sample attached and let me know whether it corresponds to your sceanario ? Is that the behavior that you want to achieve ?  

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  25. Andrew
    Andrew avatar
    28 posts
    Member since:
    Mar 2013

    Posted 03 May 2013 Link to this post

    Maya,

    I don't see in the attached example how you can changed the position list from displaying all positions (GK,DF,MF,FW) for player 1 (Fernando Torres) and displaying select positions (GK,FW) for Player 2 (Bob).  

    It seems like I can 1) display custom lists using a lookupPropertyDefinition (previous example from April 19) OR 2) display a static list of flag enum values (Example from today).  Not both.  If I could combine them to display a custom list of flag enum values, I'd be set.

    Thanks,
    Andrew
  26. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 08 May 2013 Link to this post

    Hello Andrew,

    What you can try is to handle Loaded event of FlagEnumEditor and remove the items you want:

    XAML:
    <telerik:FlagEnumEditor Value="{Binding Position}" EnumType="my:Position" Loaded="FlagEnumEditor_Loaded"/>
     
    Code-behind:
     
    private void FlagEnumEditor_Loaded(object sender, RoutedEventArgs e)
            {
                var enumEditor = sender as FlagEnumEditor;
     
                var player = enumEditor.DataContext as Player;
                if (player != null && player.Name.Contains("Fernando"))
                {
                    enumEditor.EnumItemsSource.RemoveAt(0);
                }
            }
     
    Will that approach meet your requirements ? 

    Regards,
    Maya
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

Back to Top
UI for WPF is Visual Studio 2017 Ready