How to Bind an Enum to a ComboBox in WPF
HTML-код
- Опубликовано: 10 сен 2024
- In this video, I answer the question "How to Bind an Enum to a ComboBox in WPF?".
When most WPF developers bind an enum to a combobox in WPF, they use the standard ObjectDataProvider approach. This consists of creating an ObjectDataProvider as a resource in tour wpf application. Setting the MethodName and ObjectType properties. Then you have to provide the ObjectDtaProvider MethodParameters which is the type of the enum you want to bind. Finally, you can then bind your ComboBox ItemsSource property to the ObjectDataProvider resources, which will essentially bind your enum to the combobox.
That's a lot of code, and it sucks really bad. After seeing the "official" (crappy) WPF approch to bind an enum to a ComboBox using an ObjectDataProvider, I will show you my approach.
My approach takes advantage of a custom MarkupExtension that can be used to bind an enum to a ComboBox just by setting the binding on the ItemsSource property. No need for an ObjectDataprovider.
You'll soon see why my way is the better approach to bind an enum to a combobox in WPF.
Be sure to watch my new Pluralsight course "Introduction to Prism for WPF":
pluralsight.px...
Sponsor Me:
github.com/spo...
Follow Me:
Twitter: / brianlagunas
Twitch: / brianlagunas
Blog: brianlagunas.com
GitHub: github.com/bri...
Well crap... I just realized I updated the ItemsSource property wrong in the video! You can simple use
ItemsSource="{local:EnumBindingSource local:Status}"
Sorry about that 😁
In Xamarin.Forms, it's possible you still need the {x:Type local:Status}. I just tried Dan Siegel's Xamarin.Forms snippet and got build time error from XamlC if I removed x:Type. Maybe the error would go away if I didn't do compiled bindings, but I love compiled bindings too much to disable them.
@@JacobEgnerGod to know, thanks for sharing. If only they would use a common XAML markup 😂
@@BrianLagunas Yeah, in the last Xamarin survey I took, my biggest feedback was "avoidable xaml differences between Xamarin and WPF are bad".
Oh wow. This approach is fantastic!! Really this is so much better. Thank you for sharing 😁😁
Thank you so much, Be sure to read the pinned comment as I made a slight mistake in my recording. It's even easier 😁
I'm guessing then to bind to the SelectedItem You would just do SelectedItem="{Binding SelectedObj}"? You wouldn't need any converter or extra bloated code?
@@NickBullCSharp Correct. No converters needed. The selected value will be of the EnumType.
@@BrianLagunas Oh my days, you are fantastic. This will clean up my code big time 😜. I've had to write converters in the past lol
Brian Lagunas, congratulations on the video and knowledge. I was very happy to know your channel and especially the easy and professional way you program. Greetings from The Brazil.
I appreciate that! Thank you for watching
Brian approach is really fantastic. Thanks for great video.
Thank you so much sir
Hi Brian, all your video material is good.
Glad you like them!
Thanks for the video Brian. I find them useful always.
Thanks for watching
very good sir!!!
Thank you so much
great , many thanks
Thanks for watching
Nice implementation - appreciated
Thanks for watching
hi Brian
but what if we want to bind to the same Enum after adding this Type Attribute to get the enum not the enum description??
thanks in advance.
Well, you would probably have to create another binding extension that removes the typeconverter or the description attributes before you get the values. Or, you could possibly use a converter instead.
Oh, Brian, you always delight and never disappoint. This is good stuff and I look forward to using it. I'm guessing it would work in Xamarin.Forms too?
Yeah, I don't see why it wouldn't work in XF. I'd have to try to be 100% sure.
@@BrianLagunas For the sake of other readers, there was another place where Dan Siegel confirmed Brian's answer.
Also Dan Siegel posted a gist for Xamarin: twitter.com/DanJSiegel/status/1295797588977807360
Thanks! That's incredibly cool. I didn't know about ObjectDataProvider, or how easy it is to make my own markup extension.
I'm glad I could help
Hi Brian, I have Combobox1 and Combobox2.
Combobox1 is binded to enum1 {ac, df, gj}.
Combobox2 is binded to enum2 {a, b, c, d, e, f, g, h, i, j}.
If I choose on Combobox1 value 'ac' then I want to filter options on Combobox2 to only {a, b, c}.
Do You know solutions for that?
My first thought is to use a converter
How do we use the EnumBindingSourceExtension when we are creating the combobox from C# instead of xaml?
can the same thing be done with ObservableCollections< person > ?
A private setter allows a property to be set anywhere within the class or any of its inner types.
A read-only auto property has no declared setter and can be set in the constructor but not outside the constructor..
Exactly! Thanks for clarifying. I should have used a ReadOnly property in this case, but when I am recording I don't think about everything 😂
You never stop to amaze me. Thanks for such informative videos. Long back I had watched your Prism tutorial course in pluralsight and have been following your blogs since then.
Will it work if I use a wrap panel to give a layout like in windows 10 settings. And also I would like add or remove modules without making any changes in code.
Just wanted an expert advice before starting on a personal project. Thanks in advance. 🙂
Thank you for watching. I'm not sure I understand your question completely. When it comes to layout, you can do anything in WPF. You can easily add modules at anytime with Prism. Removing modules is not a thing, but perhaps you are just wanting to remove views, which is easily done.
I don't understand how it is bound to a ViewModel. I would like to use use two-way binding. If I have a property in my ViewModel of enum type how I can bind to this property using this approach? Do I need a separate event handler or something to make it work?
It turns out that you just need to bind to SelectedItem property to a property in your view model. Another of this cases where I could say "it works, but I don't know why" :)
The power of data binding 😁
Hey Brian,
Is there is away to change the direction (RTL/LTR) of the form/control after changing the culture in WPF or Xamarin Forms using prism?
Thanks
In WPF you use a combination of the xml:lang attribute for hyphenation, spell checking, number substitution, and font fall back. You also would set the FlowDirection property on every page. You'll also need to use the x:Uid attribute. There's actually a lot that goes into localizing an application 😁
can I create this enum in mainwindow class and access it in object data provider?
if yes then please tell me how I googled it a lot but didnt find any answer.
Don't use nested types (such as nesting an enumeration within a class) when you define your code for use with XAML. Nested types can't be evaluated. There's no way for the XAML parser to distinguish that a dot is part of the nested type name rather than part of the namespace name. If you really want to do this, then you'd need to create a custom markup extension to parse the nested class to return the type properly.
I implemented the technique you described under the .NET Framework 4.8. However when I migrated to .NET 5 access to the implementation of MarkupExtension was compromised. There is no nuget package available for the assembly and manually referencing it gets me a compile error. Could you give me some advice? Thanks
Try deleting your obj and bin folders and do a rebuild.
@@BrianLagunas Thanks for the suggestion, Brian. It did not work as expected, however. I decided to search nuget for an assembly that contained all or part of System.Xaml instead. I found the Avalonia.Markup.XamlLoader (0.10.6) and it seemed to have solved the problem. I was naively under impression that migration to the .NET 5 platform would not incur breaking changes caused by someone deciding for me what core (System.Xaml is older than I am...) for me. Thanks for your great idea and thanks for your help.
Did you convert the DNF app to .NET 5 or did you start with a new .NET 5 app? I feel you may have made a mistake if you did a manual conversion. I just tested and it works fine with no added dependencies
@@BrianLagunas I used the migration tool. I am not surprised you think I may have made a mistake. It has been a real uphill battle.
Amazing video
Thank you very much
Hey Brian, Thanks for doing this series! This is a gold mine! Could you do a video on configuring core services like logging and configuration management in a Prism application?
Can you provide a little more detail on what you mean by configuration management?
Sure, what I was referring to was setting up a prism app to pull configuration data from an appsettings.json file or environment settings, for say adding modules or connection strings, while, at the same time leveraging Prisms IOC mechanisms. I guess what isn’t clear to me is which configuration components from Microsoft (host builder) duplicate some of the IOC mechanisms that prism provides and how to navigate the overlap.
Thanks!
Modules can only be added via app.config, xaml file, directory, or code out of the box. You'd need to write a custom module catalog to support JSON. Your other actions should be in a service you register with the container. Prism doesn't support the MS DI container as its missing too many features.
amazing Solution thanks!!!!!
Thank you so much
Clean coding
Thanks
👍👍
Thanks for watching
Was trying to implement same in UWP, but it didn't work. How to implement in UWP?
What didn't work? What did you try?
I like this solution. Very clean. I’ve always used an ObservableCollection populated in the constructor of my ViewModel, and bound the SelectedValue property to a Foo property in the VM. Question: how are you accessing the selected value in a view model, or are you doing it in code behind?
Now you don't need to polite your VM with another property. Just data bind the SelectedItem to a property in my VM.
Brian Lagunas of course! Get rid of the ObservableCollection, but keep the SelectedValue bind. So clean. Thanks!
Great video! Sound is synced properly also.
I had a question on injecting dependencies into a singleton class using Prism.
I have the following class:
public class Foo : IFoo
{
private static Foo instance;
private Foo() {}
public static Foo Instance => instance ?? (instance = new Foo())
}
I've registered this with the IoC container as follows:
containerRegistry.RegisterInstance(Foo.Instance);
I now want to inject the IEventAggregator into this class. How would I do that?
That static is not needed. Just register it as a Singleton. Avoid statics like that.
containerRegistry.RegisterSingleton();
public class Foo : IFoo
{
public Foo(IEvevntAggregator ea) {..}
}
Hello Brian, If there are some data in Enum that want to ignore. it's any way to do it ?
Example: there have 4 data in Enum [a, b, c , d] just want to bind [a, b, c] to the combo box.
Of course. The best way would be to add a property to the EnumBindingSourceExtension called Exclude and make it a List(string). Then use that list to filter out the values you don't want to appear in the ProvideValue method. Something like.... if (!Exclude.Contains(Enum.GetName(EnumType, item))) result.Add(item);
@@BrianLagunas Awww.. Thanks Brian
Is it possible to use a valueconverter here? (sorry wpf noob)
Mh yeah nice...but...how often do you display the values of the enum inside the ui like they are called in the code? I'm interested in a way to create a mapping of enum values and strings only inside xaml and use this for databinding in my MVVM application. Do you know a way to accomplish this without defining a dictionary in the Viewmodel?
Yes, watch this video ruclips.net/video/T1mhORJCDsY/видео.html
Hi Brian, is there a way to make Scrollviewer invisible in wpf?. I mean Scrollviewer should be there but should not be visible to the user?
I think you are talking about showing and hiding the ScrollViewer scrollbars? If so then yes, you can control this on any element that contains a scroll viewer by using the ScrollViewer.HorizontalScrollBarVisibility and ScrollViewer.VerticalScrollBarVisibility attached properties.
@@BrianLagunas in our case user should still able to scroll, but the scroll viewer should not be visible to the user
What is the best of binding svg image in wpf?
Thanks for the question
Great content Brian! Short and to the point. Any possibility of doing a vid on writing proper unit tests?
Sure. I can do a unit test video. I don't know if it'll be "proper", but it will test things 🤣. Anything specific you're trying to test?
@@BrianLagunas great! Perhaps a general video focusing on test driven development
I don't belive in TDD in general. TDD is different than just unit testing.
Thankyou very much for the video. However I would like to ask if you know a simple solution like that if we wish to convert an enum with underline in space. ex : "Days_Of_Week" >> "Days Of Week"
You would just have to modify the type converter to replace your underscores with spaces
Thanks Brian. This approach is great. The ItemSource property naming convention is a little mysterious. It seems it would be more intuitive that the convention would be ItemSource="{local:EnumBindingSourceExtension local:Status}" to match the name of the extension class instead of ItemsSource="{local:EnumBindingSource local:Status}" or is Extension just redundant and left out of the binding?
I just tried ItemSource="{local:EnumBindingSourceExtension local:Status}" and that works too!
@@tomroberts1216 Yes, this is a naming convention enforced by WPF. You can choose to add the "Extension" to the class name in the extension use, or leave it out. As you can see, either will work.
And how I bind that value to an object?
Got it working
SelectedItem="{Binding classpath}"
Does it fit for DataGrid Combobox?
It works with any combobox
Still doing WPF? I shifted to angular and love angular material UI components. Microsoft will never provide mature UI components like angular material for WPF or Blazor.
I do a little bit of everything. I am always jumping between platforms. The main platforms I work with today are WPF, Angular, Blazer, Vue, React, and Xamarin.Forms. Soon to add Uno to that list.
Hello Brain firstly thank you for your sharing. If you could please start a blazor course on youtube. It should be very useful. Thank you in advance.
Noted. Courses take a crap ton of time to plan and create, but I'll add it to my todo list.
@@BrianLagunas thank you Brain. Your teaching tecnique is very clear. I like to learn from your vidoes. Good job.
Thanks for the video. Why can't just use an converter for this?
You can use a converter, but this actually requires much more code, and is way more limiting. For example; you'll need to expose a collection on your VM that represents your Enum to data bind to, then create a converter with your converter logic, which must be defined as a resource in xaml and then added to the binding. Localization becomes more of a challenge as well.
@@BrianLagunas thank you for your time Brian
What if the Status class have multiple class of Enum ??
I'm sorry, I do not understand. Status is not a class but an enum. Could you try to explain differently?
@@BrianLagunasSorry for poor explaination. it's mean Status.cs inside have multiple of Enum, when binding the item source is just following the Enum name instead of Status ?
Yes, you would provide the type of the enum, not the name of the .cs file.
@@BrianLagunas Thanks Brian. Learn a lot from your video.
I take it there is no way to do this with multi language support? Mic sounds much better by the way.
The only way would be with language subtitles, bu I can't afford that 😁. Thanks for the mic feedback. I'll stick to this mic from now on.
@@BrianLagunas I mean in a wpf program, multi language support using this way to bind.
@@davidwhite2011 Ahhh.. So you want to be able to localize the enum in the combo box? So if I am in Japanese the enum values will be displayed in Japanese in the comboBox, but the underlying value will still be the enum type?