Add your own alternative version
Stats
109.3K views 515 downloads 23 bookmarked
Posted
19 Jun 2007
|
Comments and Discussions
|
|
This approach just creates a non-localizable app. Very bad.
|
|
|
|
|
Actually, this approach lends itself to localization with a single point of translation for the enum.
Just spitballing here, but you could modify the helper function to look up the localized text, using the enum name as the key and return an array of these localized values.
Or - simply not use enum's in your combobox
Or - come up with another way.
Purpose of the article was not to be a, "one size fits all solution", but rather show the capabilities of WPF and a possible method of using an eunum.
Cheers, Karl
Just a grain of sand on the beach.
|
|
|
|
|
Karl,
Thanks for taking the time to write this article! This is a very practical subject matter, which I'm sure will be useful for many people through the years.
I don't mean to rain on your parade, but there is actually another way to implement this functionality which is truly 100% XAML-only. It is possible to remove the method in the code-behind which sorts the enum values. Here is a XAML-only solution:
The unsorted enum:
public enum Animals
{
Zebra,
Antelope,
Ox,
Mouse
}
The XAML which displays the enum values, sorted, in a ComboBox:
<Grid
xmlns:local="clr-namespace:WPF_Test"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
>
<Grid.Resources>
<CollectionViewSource x:Key="SortedAnimalsView">
<CollectionViewSource.SortDescriptions>
<cm:SortDescription />
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.Source>
<ObjectDataProvider
MethodName="GetNames"
ObjectType="{x:Type sys:Enum}"
>
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:Animals"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</CollectionViewSource.Source>
</CollectionViewSource>
</Grid.Resources>
<ComboBox
DataContext="{StaticResource SortedAnimalsView}"
ItemsSource="{Binding}"
VerticalAlignment="Center"
/>
</Grid>
As you can see above, the CollectionViewSource which the ComboBox binds to can have a SortDescription added to it. That will take care of sorting the enum values for us.
Thanks again for posting this article!
Josh
|
|
|
|
|
Josh,
Thank you for a very detailed insite into WPF. Really appreicate your teaching.
Have a great day!
Karl
Just a grain of sand on the beach.
|
|
|
|
|
Karl_Shifflett wrote: Thank you for a very detailed insite into WPF. Really appreicate your teaching.
It's my pleasure, Karl.
:josh:
My WPF Blog[ ^]
FYI - Bob is a scarecrow who keeps Chuck Norris away from CodeProject.
|
|
|
|
|
Karl,
I decided to blog about your article and my alternate implementation here[^].
:josh:
My WPF Blog[ ^]
FYI - Bob is a scarecrow who keeps Chuck Norris away from CodeProject.
|
|
|
|
|
Josh,
Thank you!
Just a grain of sand on the beach.
|
|
|
|
|
In C# code this would be an order of magnitude shorter and more readable, why use xaml? Just curious, since I haven't really played with xaml yet.
Wout
|
|
|
|
|
Yes, you can do the same thing in VB.Net with a shared method in the code behind page, one line of .Net code.
The idea here is, you can do it without code in .xaml.
Depending on the project..
Just a grain of sand on the beach.
|
|
|
|
|
Why do you entitle the article "...without code"? If you look carefully, I think you'll see that some code is being used.
Perhaps a name change is in order.
|
|
|
|
|
Idea being, without code in the code behind page.
Same idea as "no code data binding to a sql database." Using the object data source you can data bind without code to a sql server database. However, the method, that the object data source binds to, has code in it.
Basically, a developer "could" write the helper code and the "designer" could use the method "without code."
Just a grain of sand on the beach.
|
|
|
|
|
in real life scenario, this would not help much i believe. cause we often need to display a user readable text rather displaying an Enum value. for example, if an enum is like
<br />
enum IssueStatus<br />
{<br />
Initiated,<br />
Active,<br />
InProgress<br />
Finished<br />
}<br />
Now a combox box on UI should display "In progress" (notice the whitespace between In and progress) rather displaying the InProgress - which is not intuitive.
Therefore, you can create some sort of custom Attribute to define the alias for a enum value and bind those alias value rather binding with the enum value.
Keep up good works!
Moim Hossain
Sr. Software Engineer
Onirban Orion Technologies.
|
|
|
|
|
Good points. This is not a one size fits all solution.
Here is where this came from :
Public Enum MaritalStatuses
[Single]
Married
End Enum
Public Enum PayFrequencies
Monthly = 12
Weekly = 52
BiWeekly = 26
End Enum
My demo this weekend is a TaxCalculator developed using Blend. I needed to referece a .dll with the above enums.
In this case, the solution allows data binding to these enums without requiring code behind.
Let me think about a way to render a more user friendly version of "InProgress" or in my case "BiWeekly"
You "could" change InProgress to In_Progress and then replace the "_", but then, when you convert the value back to an enum, you would need to replace the space with an "_".
I was also thinking about this the other day.
I spitbally here, another solution could be, instead of returning an array of strings, return instead an array of objects that represent the enum in a very usable way.
The objects could have the following properties, Title, Name, Value. Then use logic or your attribute to set the Title propety the user friendly way.
Have a great day and thank you for the comments.
Karl
Just a grain of sand on the beach.
|
|
|
|
|
Hi!
Don't you think GetSortedEnumNames makes more sense as a static method (shared in VB.NET)?
P.S.:
Oh, and isn't there a way to determine the type of an object in VB.NET without having to use GetType().ToString() and a literal string comparison? Something like the "is" keyword in C#?
Regards,
mav
--
Black holes are the places where God divided by 0...
|
|
|
|
|
mav,
Yes, you are correct, this function could be shared, then any VB.NET or C# code could use it as such and the object data source also.
The code : If t.BaseType.FullName = "System.Enum" Then doesn't use the .ToString method. It's just a property.
I'm like you. I don't like string comparisions in my code (if possible).
However, I tried hard before I chose this method, however I do not think it's possible. I went through the object browser and used the debugger to see my options and t.BaseType.FullName was my best option.
Cheers,
Just a grain of sand on the beach.
|
|
|
|
|
I think you missed the point here with the ToString() thing. This is still doing a string comparison to check the equivalence of two object types, whether it is using the FullName property or not.
In c# you have a typeof() operator (sorry I am primarily a C# developer). So in C# this would be done as:
if (t.BaseType == typeof(System.Enum))
I looked it up in VB.Net and you can do this:
If TypeOf t.BaseType is System.Enum Then
... which compares the actual System.Type objects for the two expressions instead of doing a string compare. Although I will have to take someone else's word for it that this works since I haven't developed in VB since VB6.
Boh
|
|
|
|
|
boh,
Thank you for continuing the thread. I had to make a slight adjustment to your suggestion for the VB.NET syntax, but this is a better solution.
Thank you!
Public Shared Function GetSortedEnumNames(ByVal t As Type) As String()
'first do a sanity check, make sure the developer is passing us an enum
If t.BaseType Is GetType(System.Enum) Then
Dim strOut() As String = [Enum].GetNames(t)
Array.Sort(strOut)
Return strOut
Else
Throw New ArgumentException("Must be an enum", "t")
End If
End Function
Cheers, Karl
Just a grain of sand on the beach.
|
|
|
|
|
Why not just use the IsEnum method?
Public Shared Function GetSortedEnumNames(ByVal t As Type) As String()
'first do a sanity check, make sure the developer is passing us an enum
If t.IsEnum Then
Dim strOut() As String = [Enum].GetNames(t)
Array.Sort(strOut)
Return strOut
Else
Throw New ArgumentException("Must be an enum", "t")
End If
End Function
Regards
Neal
|
|
|
|
|
Neal,
You are the Man!
Love to learn new things about .Net everyday.
Thank you for sharing your knowledge.
Cheers,
Karl
Cheers, Karl
Just a grain of sand on the worlds beaches.
|
|
|
|
|
mav,
Here is a the code behind version. Without any doubt, this one line of code is shorter and easier too. This below code assumes the function is changed to a shared function. Basically, I was demonstrating that this could be done.
Private Sub FillComboboxWithSortedEnumDemo_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Me.cboZooCreatures.ItemsSource = Helpers.GetSortedEnumNames(GetType(ZooCreatures))
End Sub
Shared Function Version Of Helpers
Public Class Helpers
Public Shared Function GetSortedEnumNames(ByVal t As Type) As String()
'first do a sanity check, make sure the developer is passing us an enum
If t.BaseType.FullName = "System.Enum" Then
Dim strOut() As String = [Enum].GetNames(t)
Array.Sort(strOut)
Return strOut
Else
Throw New ArgumentException("Must be an enum", "t")
End If
End Function
Public Sub New()
End Sub
End Class
Cheers and thank you!
Just a grain of sand on the beach.
|
|
|
|
|
|
General News Suggestion Question Bug Answer Joke Praise Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
|