WPF Combobox Itemssource is Visibility Enum - c#

So i have a simple question; I want to display the System.Windows.Visibility Enum in a ComboBox. However i don't seem to find the path to it. Searched like a crazy man but couldn't find anyone who know the path to this enum.
I'm aware that this can be done in code (and already have it working) but i prefer to do it in XAML.
Could anyone help me out?

Voila:
<ComboBox SelectedIndex="0">
<Visibility>Visible</Visibility>
<Visibility>Collapsed</Visibility>
<Visibility>Hidden</Visibility>
</ComboBox>
No additional namespaces needed.

#Maciek's solution is the simplest and quickest to apply, however more general, pure XAML way of listing enum values is this:
<FrameworkElement.Resources>
<ObjectDataProvider x:Key="ItemsSource"
ObjectType="{x:Type sys:Enum}"
MethodName="GetValues"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="Visibility" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</FrameworkElement.Resources>
(...)
<ComboBox ItemsSource="{Binding Source={StaticResource ItemsSource}}" />
You can then simply replace Visibility with any other enum type to get a list of its values.

If you want to bind enum values to ItemsSource, you need a property in ViewModel with enum values. Than you have to bind ItemsSource to this property. You get values of enum like this:
Enum.GetValues(typeof(EffectStyle)).Cast<EffectStyle>();
If you can't find a path to your property, that means you have wrong DataContext. Set it to your ViewModel class or to your window, if your are not using MVVM. In the simplest scenario, you could set DataContext to your window in Window constructor.
this.DataContext = this;
Take a look at this or this link, as a big picture of DataContext and Binding in WPF.
If you are interested, also read about MVVM in WPF. You could use MVVM Light
If you want a fully xaml solution for your enum binding to ComboBox, you could write sth like this or use ObjectDataProvider like here.
I think Maciek's solution is good enough in your case.

If you want to do it using code, let's say your combobx has an x:name = my combo you can simply do:
mycombo.ItemsSource = Enum.GetValues(typeof(Visibility)).Cast<Visibility>();

Related

DisplayMemberPath Behavior

I was wandering if someone can explain to me how the Dependency Property DisplayMemberPath works?
I am trying to create Custom ItemsControl that has property like DisplayMemberPath of a ComboBox, in otherwords after setting the ItemsSource I want to be able to specify the Property to Display.
At the moment if I do somthing like:
<cc:MyControl ... DisplayMemberPath="MyObjectDescription" ... >
(Yes I have overridden the DisplayMemberPath, its besides the point).
It displays a list of items, but they each Display "MyObjectDescription", instead of the value that that Property holds for each object in the ItemsSource.
And I believe its because I am missing something in regards to how DisplayMemberPath Property works.
Thanks All. :)
There are two types of DisplayMemberPath. One that supports Binding and one where you have to set a string value. In your case as I can see you wish to implement the second one. To do so create a property inside your custom control of type string and name it DisplayMemberPath. Override the methode OnInitialized in your container with your custom logic where you tell the container to manipulate the path of the binding to DataContext by changing binding's path to the string value as you specified in DisplayMemeberPath. WPF calls OnInitalized once any control is completely initalized but before its about to get rendered. I hope this helps you any futher.
I'm assuming your control is like MyControl and MyControlItem like ListBox and ListBoxItem.
You can access the DisplayMemberPath of MyControl when the MyControlItem is being created and use it to get the data from the DataContext.
Bit late to party, but maybe other could be helped
If your purpose is barely to use Itemscontrol over ListBox/View, you may consider to define the Datatemplate for the itemscontrol's Items instead of packing this in a Usercontrol:
<ItemsControl ItemsSource="{Binding myObjectCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding myObjectProp}"/> (or whatever...)
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

ComboBox for enumeration System.IO.Ports.Parity in WPF

I want (in C#) to populate the list of admissible values for a combobox with the admissible values of the enumeration System.IO.Ports.Parity. To this end I created a collection:
public class theParitySource : ObservableCollection<Parity>
{
public theParitySource()
{
Array parities = System.Enum.GetValues( typeof( Parity ) );
foreach (Parity p in parities) this.Add(p);
}
}
(btw: is there oneliner for this initialization?) and made this the datacontext of the combobox:
...
xmlns:local="clr-namespace:myNamespace"
...
<ComboBox ...>
<ComboBox.DataContext>
<local:theParitySource />
</ComboBox.DataContext>
</ComboBox>
The combobox, however, remains empty (it is shown as empty, but seems to have the correct length), even though I can see in the Debugger how theParitySource gets populated. This approach does work in another combobox (even in the same class) where I do this for a baudrate. That I initialize with integer values, so I guess it is somehow related to the fact that I'm using an enum here, but I'm clueluess what might be the reason. Any pointers? Do I need to write a converter?
(Of course I can work around this by creating a list of strings from the enum, but this would be kind of unpleasant...)
Edit: actually I'd prefer to do all of this in XAML. Is there a simple way to do that?
You can do this all in the Xaml using ObjectDataProvider
In your Window.Resources (or whatever resources you are using) setup a ObjectDataProvider.
To setup the ObjectDataProvider for Enums you set the ObjectType to {x:Type sys:Enum} and the MethodName to GetValues to fill the ComboBox with the actual Enums or you can use GetNames to fill the ComboBox with a string representaion of the Enum
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:io="clr-namespace:System.IO.Ports;assembly=System"
<Window.Resources>
<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="ParityValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="io:Parity" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
Then bind to your ComboBox
<ComboBox ItemsSource="{Binding Source={StaticResource ParityValues}}" />
Result:
You need to bind to a proper path, you might be setting its data context, but you're not telling it with property to display.
You need to tell it what part of the bound context you are wanting to display and which you are wanting to be 'selected'.
WPF Combobox DisplayMemberPath

DataContext in WPF

I am trying the following in my WPF application:
Structure of XAML elements.
DataTemplate[Data Type 'A']
Grid
Broder
TextBlock
I want to bind the text block's text property to a "string" which is derived from my "Users" class which is referenced in the resource dictionary of the XAML.
So in the above structure since the DataTemplate gets the feed from data type 'A'.
I want to assign the datacontext(Users) to the grid and bind the string to the textblock.
Is there a way i can achieve this ,since all my trials which include assigning the datacontext to the Grid or Border or TextBlock doesn't work.
Can any one suggest me or correct me if my approach is wrong here ?
This markup should suffice:
<DataTemplate DataType="{x:Type local:A}">
<Grid DataContext="{Binding Path=Users}">
<Border>
<TextBlock Text="{Binding Path=PropertyOnUsers}"/>
</Border>
</Grid>
</DataTemplate>
Make sure you have the namespace declared at the top of your Xaml. For whatever reason, WPF doesn't always automatically infer the template from the type if you don't use {x:Type ...}.
From there it should be straight forward.
If Users is a collection, you will have to drill into the collection to get a specific instance of User.
By the way, if you are using Visual Studio, you can use the Output window to debug binding issues.

Understanding DataBinding

I'm new to WPF and the whole data binding thing. I read a couple of posts and I'm quite confused about how to bind my data to a UI element.
I saw a post doing it this way:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myWindow">
<Grid>
<TextBox Text="{Binding Path=Speed, ElementName=myWindow}" />
</Grid>
</Window>
This assumes Speed is a property / member defined in the code-behind file. A few other people named binding using a static resource and reference this one and others named DataContext to be used for binding. Now, because I'm new to WPF's data binding, I'm quite unsure if there exists any best practice method about which data binding to use.
Basically I was wondering why there has to be a several class-property defined as kind of connector to the underlying viewmodel, I though this stuff was more "dynamically".
I'm aiming at only having the XAML file, without the need to add anything into the *.xaml.cs code behind file. For example: I have a class named MainWindowViewModel (which will represent my ViewModel) having a member of the type ObservableCollection<string> and I want to bind a ListBox (in my View) to this collection. The only way I got this working so far was using the the first case, ElementName, where I have to add a property to the view-class as a kind of connector. Just like this:
MainWindow.xaml:
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="MW" Title="MainWindow" Height="419" Width="463">
<Grid>
<ListBox ItemsSource="{Binding ElementName=MW, Path=ListerResultConnector}" />
</Grid>
</Window>
MainWindow.xaml.cs:
private ObservableCollection<string> mListerResultData = MainWindowViewModel.Instance.RetrievalStringResults;
public ObservableCollection<string> ListerResultConnector
{
get { return mListerResultData; }
}
My question is, if there exists a smarter way to bind data to my UI as using as further "connector" property in the code-behind file.
Your ViewModel should be set as the DataContext to the view. Then you don't need any "further connector" in codebehind. Binding actually refers to DataContext and if you don't set it, it remains as 'this', which corresponds to your codebehind file (which is just a partial to your view).
Also, take a look at: WPF Apps With The Model-View-ViewModel Design Pattern
You should get the WPF and it's binding basics first, but once you understand those, I suggest looking at Caliburn Micro and its convention-based bindings, event handling and other features which make your code much cleaner.
Your {Binding ElementName=MW means you are binding to the Window itself, so your DataContext is the Window, and any properties you implement need to be defined in that Window (in your code behind - your "connectors").
You need to remove the ElementName=MW bit and assign your ViewModel as the DataContext so you can bind to its properties directly. How you do this depends on whether you use "ViewModel First", or "View First"
In View first, you manually assign the DataContext to the View in code when you create the view.
In ViewModel first, you create a DataTemplate in XAML that ties your View to a particular ViewModel. I think ViewModel first is more common. The link that Darjan posted should help you understand the difference.
You should use a separate ViewModel class (WindowViewModel) which represents your data context for your Window (Window.DataContext).
I found that using the MVVM Light toolkit and following some of the videos on the site helped me fill in the gaps. Take time to learn it before getting started and it will start to sink in. IoC containers are also mixed in with MVVM + WPF for directory management & lifetime management of view models and improved design-time experience (blendability).
Toolkits aren't required and sometimes get in your way of learning the pattern. Once you understand it though, you should leverage a toolkit to speedup the development process. Here is a comparison of various MVVM toolkits.
A binding generally has two parts: a source object and a property name
When you specify ElementName in a binding, you are setting the Source object. Other ways to specify the binding's source object include the RelativeSource and Source properties. You can also leave the binding's source object undefined, in which case it will use whatever the DataContext is of the current object. The Source Object can be a UI Element found in WPF's VisualTree, or it can be a class object that is in the control's DataContext
When you specify Path, you are telling the binding what Property to use. You can also leave this property blank to bind to the current object's DataContext
The DataContext is the data object stored behind the control. This is typically a Model or a ViewModel (if using MVVM), although it can also be almost any object, such as a UI Element.
In your example
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myWindow">
<Grid>
<TextBox Text="{Binding Path=Speed, ElementName=myWindow}" />
</Grid>
</Window>
you are telling the binding that it's Source Object is the UI Element in the Visual Tree named myWindow, and the property is called Speed. Since your object named myWindow is of type Window, this binding will only work if your Window class actually has a property called Speed.
There are a lot of answers here suggesting you switch to using the MVVM design pattern, and I agree that you should try and use MVVM if you're working with WPF. It makes coding a lot simpler since you are separating your application logic from your UI. If you're interested, I have a simple MVVM example posted on my blog which explains the basics of that design pattern.
Yeah, Binding is nothing if not confusing.
This example from msdn may be helpful. Notice how a DataContext is declared at the Window "level" - it's a complex/compound object in this case and Window sub-elements' {Binding} declarations are therefore implicitly relative to the "Parent level" DataContext.
The main goodness we get is that when the DataContext is set to a given object all the "sub element" data bindings are automagically keep in synch. We can control this synchronization at any/many levels in the UI Control structure heirarchy by using this pattern.
Collection binding under the hood
The bottom line is your collection must implement IList as a minimum. Many .NET Collection classes are "binding ready."
Here's a quote from the msnd doc on ObservableCollection:
Before implementing your own collection, consider using ObservableCollection or one of the existing collection classes, such as List, Collection, and BindingList, among many others. If you have an advanced scenario and want to implement your own collection, consider using IList, which provides a non-generic collection of objects that can be individually accessed by index. Implementing IList provides the best performance with the data binding engine.
Finally, IBinding list vs IList is needed for 2-way binding.
The simplest way to do it would be:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:WpfApplication4"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ctrl:MainWindowViewModel x:Key="mym" />
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource mym}}">
<ListBox ItemsSource="{Binding Path=MyListProp}" />
</Grid>
The example above does the following:
Creates a new object of the ViewModel as resource for you window
Assigns the view model as DataContext for the window (more precisley for the root grid)
Binds the List box to your ViewModel ObservableCollection property MyListProp.
Try to get familiar with the properties of the binding class to fully understand this example by using the msdn library.
Also WPF 4 Unleashed - Adam Nathan is a great resource for a wpf beginner. Chapter 13 - Data Binding should cover everything you might want to know about bindings.

WPF context menu bound to List<> dependency property

Im trying to make the contents of a List thats a dependency property show up in a WPF context menu.
I have a class with the following dependency property, a list of Foo's (data holding class):
public List<Foo> FooList
{
get { return (List<Foo>)GetValue(FooListProperty); }
set { SetValue(FooListProperty, value); }
}
public static DependencyProperty FooListProperty =
DependencyProperty.Register("FooList", typeof(List<Foo>),
typeof(FooButton));
In XAML I set up the following static resource, I assume its needed since the context menu isnt part of the visual tree:
<UserControl.Resources>
<ResourceDictionary>
<CollectionViewSource
x:Key="FooListSource"
Source="{Binding FooList}"/>
<!-- ... -->
</ResourceDictionary>
</UserControl.Resources>
Also part of the ResourceDictionary above is a CompositeCollection which is needed to make the items show up in the actual context menu. If the UserControl CanStop property is true, we also show a separator and a stop command. These bindings does also fail, although the MenuItems themselves show up. So If I can figure out why these fail, the List might be easier.
<CompositeCollection x:Key="FooListItems">
<CollectionContainer
Collection="{Binding Source={StaticResource FooListSource}}"/>
<Separator
Visibility="{Binding CanStop,
Converter={StaticResource VisibleIfTrue}}" />
<MenuItem
Command="{x:Static Buttons:FooButton.Stop}"
Header="Stop"
Visibility="{Binding CanStop,
Converter={StaticResource VisibleIfTrue}}"/>
</CompositeCollection>
And finally the context menu itself, also in the ResourceDictionary:
<ContextMenu
x:Key="FooButtonMenu"
ItemsSource="{Binding Source={StaticResource FooListItems}}"
ItemTemplate="{StaticResource FooListTemplate}"
<ContextMenu.CommandBindings>
<CommandBinding
Command="{x:Static Buttons:FooButton.Stop}"
Executed="Stop_Executed" />
</ContextMenu.CommandBindings>
</ContextMenu>
I feel Im posting way to much code but Im not sure I can make this piece any simpler. Only the separator and the hardcoded menuitem shows up. So something must be messed up with the bindings. Bindings are usually not that hard but now when I want to bind something thats not really part of the same tree I feel a bit lost.
Any suggestions are welcome. :)
As you suspected, your problem does seem to be caused by the use of List<Foo> instead of ObservableCollection<Foo>. Since List<Foo> doesn't notify on property changes, the only way to get WPF to recognize you've added or removed an item is to temporarily set the FooList property to something else and then set it back.
There is no need to switch to a CLR property. Just change List<Foo> to ObservableCollection<Foo>.
The reason the bindings in your CompositeCollection aren't working is that CompositeCollection is not a DependencyObject, so it can't inherit a DataContext.
I don't see why you've made FooList a dependency property. You're not making it the target of a binding, which is the most common reason to create a dependency property. You haven't implemented a callback, so it can't do change notification (the second most common reason to create a dependency property). You're not using it for value inheritance. So why, then?
It seems to me that what you really want is for FooList to be a normal CLR property of type ObservableCollection<Foo> (or any class that implements INotifyCollectionChanged). That will do all the change notification that you need - at least, that you need for the code you've posted so far.

Categories

Resources