Coming from a WinForms background, I'm a little surprised to see that most (if not all) of the field-related properties for things like ItemsControls in WPF lack any sort of dropdown list for selecting fields.
For example, when using a ComboBox, if I bind the ItemsSource to a strongly-typed collection on my ViewModel in the designer, the DisplayMemberPath and ValueMemberPath properties require that I type in the names of the appropriate fields manually. My previous WinForms experience is that when binding to a strongly-typed list (in particular, a source that implements ITypedList), I would be given a dropdown of available fields so that there's no chance of fat-fingering the field name.
Am I doing something wrong here, or is this just not something that's been baked into WPF yet?
Edit
I know that this functionality was provided by the ITypedList interface in WinForms, but my understanding was that the System.ComponentModel approach to binding (PropertyDescriptors, ITypedList, IBindingList, and IListSource) were not used in WPF. Things like data grids seem to have no problems obtaining a list of fields to create columns, so I'm just curious if (and/or why) these properties that are intended to represent property names do not provide the same level of functionality.
In WPF properties like DisplayMemberPath and ValueMemberPath aren't just properties - an example might be:
<ComboBox
DisplayMemberPath="Addresses[0].Line1"
ValueMemberPath="Address[0].Id"
SelectedValue="{Binding Path=FavoriteAddressId}"
...
/>
If the designer properties only let you select from a list of properties, you'd be missing out on some pretty useful features. But you are right that providing a list in addition to being able to type it in would be useful.
There's always been a power struggle between WPF's binding system, which is quite dynamic, and the team's vision for tooling which requires a certain amount of rigidity. This is one of those cases that probably fell in the gap.
Edit: PropertyDescriptors, IBindingList and some other components of Windows Forms binding are used in WPF too - for example, my MicroModels library relies on PropertyDescriptors to work, and is built for WPF. Silverlight however doesn't support many of these.
I think this is a bug in the WPF toolkit. Check Stack Overflow question ValueMemberPath Binding in AutoCompleteBox WPF only returns top result in last name search?.
I think it has the answer to the problem.
When setting the DataContext in code it is extremely difficult for the designer to determine the type that is being bound to.
When assigning the DataContext in XAML it is much easier and although there is no drop-down in the XAML editor, when you click the little square behind the property name in the properties box you can select the properties.
In addition you can even use a design-time datacontext to add design-time types and data (beta2 related post but still valid)
My guess it is a missing feature of the XAML-editor.
Related
I am going crazy trying to figure out how to manipulate telerik RadGridView for WPF's column filtering from my ViewModel. I thought I might be able to bind the value of a FilterDescriptor to a ViewModel property, but I get
Cannot find governing FrameworkElement or FrameworkContentElement for target element
<telerik:CompositeFilterDescriptor>
<telerik:FilterDescriptor Member="Foo.SomeProperty" Operator="IsContainedIn" Value="{Binding SelectedThings}" />
</telerik:CompositeFilterDescriptor>
where Foo.SomeProperty is a VM property bound to a grid column and SelectedThings is a VM property containing a stringified array of unique values to filter against.
GridView is bound to a QueryableCollectionView.
I want the filtering to work at runtime, based upon some custom logic in the VM - ex. user clicks some button and the VM restricts distinct values of one of the columns.
This shouldn't be so hard. I must be approaching this wrong. I've been pooring over other stackoverflow questions but haven't found a solution that works yet. Any suggestions would be appreciated.
UPDATE
I would still like to achieve this with a completely MVVM approach, but for the time being I've decided to stop going nuts over it and resolve the issue in the following way.
ViewModel's ObservableCollection which is bound to a list of checkboxes representing some filtering criteria are updated by the user through the GUI.
Upon that property change the ViewModel sends a message via Messenger (MVVMLIGHT) which in the codebehind has registered to receive. The message includes the filtering criteria information.
The codebehind receives it and applies it directly to the GridView.
What's nice about this is it avoids having to wire up any DependencyProperties or other event handlers and allows the VM to remain ignorant of the View implementation. It's simple and it works.
Yes, there's a little code behind now, but until I can find some better info on how to solve this problem purely through MVVM binding, this is a workable solution.
Wish I'd done this at 9 AM yesterday instead of banging my head against the wall all day long reading Telerik's crappy documentation and hunting for examples of how to do it "the right way". Meh.
Currently I have a UserControl that displays collections of data in the same layout. So one control could be instanced with a collection of ObjectA and another of ObjectB. I then use TemplateSelectors to choose the right DataTemplates.
Later on we thought we'd set the List as a GridView to show more information in the list itself. However each type of object has different properties and the columns may have different names and not the same quantity. I realized then that the columns and such where not set in the ItemTemplate but at the GridView itself and ListView of course has no templateSelector for itself.
I wasn't sure how to do it but several ways came into mind.
1) There is some kind of TemplateSelector property I'm not aware off.
2) I CAN set it somehow at the ItemTemplateSelector only don't know how.
3) I could do the GridView dynamically (could be difficult and wan't to avoid).
Any good way to do this, tutorials or similiar I could use?
EDIT:
As I have learned a little bit more about ListView and it's view property I'm pretty sure I could define the gridview in a staticResource. Still I would love a ViewSelector or something similar. I guess this was of course not intended as the the item could be dynamic while the Collection isn't.
But I'm thinking about cases where there could exist more types of view then gridview ( iconview or something else) and the user could switch between them it would have to be implemented in some way.
The solution I see know is using a trigger and basing it on the first item in the collection but I'm not liking that too much.
Have you looked at the AutoGeneratingColumns property of the Grid?
http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.autogeneratingcolumn(v=vs.95).aspx
I am eager to find some solid (free, Open Source, or tutorial/example) code to make a WPF Combobox do autocomlete/autofilter as the user types. But everything I've tried so far has had some sort of problem...
A Reusable WPF Autocomplete TextBox came close, but I can't get it to work with more than one filter (more info here).
WPF autocomplete textbox/combobox doesn't work for me because it inherits from UserControl, and thus doesn't support the DataTemplates I need (for showing/selecting the value of one property for an object with multiple properties).
Automatically Filtering a ComboBox in WPF didn't work because it doesn't seem to ever find the EditableTextBox portion of the inherited ComboBox code (via (TextBox)base.GetTemplateChild("PART_EditableTextBox") which seems to always returns null).
Building a Filtered ComboBox for WPF just gets stuck in a refresh loop then overflows the stack after I type just a few letters.
Other things I've considered:
I know that Windows Forms' Combobox control has AutoCompleteMode and I could embed it in WPF, but I can't imagine it would play very well with my WPF data bindings.
Perhaps it is too complex and I need to simplify, maybe by building one-dimensional (single-property) ObservableCollections for the ComboBoxen... However, the challenge of applying multiple filters (one set by another control's value, and one from what the user is typing) to multiple controls using different views of the same DataSet would require a ridiculous amount of processing power to destroy and rebuild the list every time the user types a character!
So... I'm at wit's end. Any suggestions?
If your Combobox has some data source attached to it ,
just make
1-IsTextSearchEnabled = true.
2-IsEditable = true.
you are good to go
Try this one:
http://blogs.windowsclient.net/dragonz/archive/2010/02/23/autocomplete-textbox-control-for-wpf.aspx
I'm using PRISM (and thus the MVVM pattern). I've got a complex DateTime picker view with radio buttons.
The user can pick today, yesterday, a date, a week of a year, etc. I use radio buttons for the different choices.
What's the best way to do that in MVVM?
I really can't think of a clean way. I could create lots of custom behaviors to add to each item to track them but it doesn't seem maintainable.
I'm going to put some code-behind but I really don;t like that and to me it breaks the MVVM principle (put everything in the XAML).
Does anyone have a better idea on how to go about that?
Keep the RadioButtons, add an enum type to your VM that can return things like "Today" "Yesterday" or "Tomorrow." On the UI side create a ValueConverter that takes a parameter like "Tomorrow" and compares it with the bound value on VM, then returns the bool? needed by IsChecked.
Put it in code behind.
The M-V-VM pattern is not "put everything in xaml" it's "separate concerns". Your VM wants a DateTime right? In which case it doesn't care how that DateTime is being chosen it just needs a DateTime.
Putting View logic in the ViewModel isn't a good idea as you're now giving the VM knowledge about the workings of the View. The flow is meant to be View knows about the ViewModel which knows about the Model. The reverse is not normally true. (As with all things computer related there is always exceptions)
Hope this helps.
How about a ComboBox instead of the RadioButtons presenting a list of TimeOffset (custom class) bound to your ViewModel, with a corresponding SelectedTimeOffest property.
If you need to display extra information depending on the type of TimeOffset, e.g. a WeekOffset (subclass of TimeOfset) with a WeekCount property, have a content control with several DataTemplates customized by the type of TimeOFfset.
Just an idea...
you could create a enum, bind the values of the enum to a listbox, retemplate the ListboxItems
this post is using silverlight, but something similar should work
http://leeontech.wordpress.com/2009/03/18/creating-radiobuttonlist/
The ViewModel is designed to present the model in a way the view can consume.
In this case, you could have a boolean property for each button in the VM, and when a button updates it just sets all the other properties to false. Then in your View you can bind each properties IsChecked to the corresponding property in the ViewModel.
Also, be aware there is currently a bug in binding radio buttons in WPF. Here's a potential solution.
Over at the StackOverflow question How can WPF Converters be used in an MVVM pattern? I've learned that Value Converters should not be used in the MVVM pattern since the functionality of a Value Converter should be handled by the ViewModel itself.
This makes sense.
But I remember reading that you should not expose XAML elements to the View, but instead expose only collections of data which the View then binds and displays using DataTemplates.
However, converters seem quite powerful (e.g. as they are used in the MVVM Template demo, see the "Messenger Sample" after unpacking it) in that they can convert objects to objects, e.g. Message objects to FlowDocument objects, or Customer objects into Visibility objects, or custom Status objects into Images, etc.
So if a ViewModel is going to take on the functionality of a Value Converter, it is going to have to expose XAML elements and properties such as StackPanel, Visibility, Color, FlowDocument, etc., right?
Does anyone see any reason why a ViewModel should not expose these rich XAML objects as Value Converters do?
Because then that limits the ViewModel to be used only with a specific visual representation.
Once you have the ViewModel emitting XAML, it puts design content into a developer's domain.
This means that the designer using Expression Blend cannot edit design assets - and the designer/developer workflow is broken.
Keeping the XAML on the page and using Value converters with data templating keeps the design separated from the code.
When your ViewModel exposes specific XAML it also limits that ViewModel to be used only in that specific instance and makes it less reusable.
Don't forget that you can use DataTemplates too. I can see some sense in keeping ValueConverters out of MVVM, but DataTemplates are all about transforming objects into GUI.
Your ViewModel can expose other objects (e.g. nested ViewModels) to the GUI, and the GUI can use <DataTemplate DataType="{x:Type SubViewModel}">... to map those objects to GUI.
Does anyone see any reason why a ViewModel should not expose these rich XAML objects as Value Converters do?
Absolutely, because it undermines all the goals of MVVM:
You're no longer unit testable, at least not easily.
You no longer have separation between logic (view model) and presentation (view). Thus, designers and developers cannot easily collaborate.
Code maintenance is more difficult because you've mixed the concerns together.
If I saw a view model returning a view, I wouldn't even classify it as MVVM.
I think one idea of mvvm/mvc/mvp etc. is to isolate the GUI code to one file/class.
If you do this can you change to some other UI without rewriting the other objects?
I think if you're passing around WPF specific objects the answer is no.
It's a value judgment you'll have to make for your self.
There is no absolute 100% rule that works for this or many other concepts when you discuss them without the perspective of why the community's mind has shifted as it has in this direction. There is no 'assumed' truth or science in 'conventional wisdom' regardless of how new or compelling it is at the time.
In other words - just do the best with your team as if your good, your already getting pulled down far more in human concerns than anything as real as this.