Best practice for forwarding ItemsSource - wpf

I have a UserControl that contains - among other things - a ListView. The ListView has a different data context than the UserControl (this data context is not exposed). If someone consumes my control, I would like them to be able to (indirectly) bind to the ListView's ItemsSource dependency property. It should really feel like the user is binding to a typical ItemsSource.
I'm not sure what the best way to proceed is. Looking at how ItemsControl's ItemsSource property worked in Reflector showed some logic that seemed a bit more involved than ought to be necessary for simple forwarding.
My current best idea is to expose a collection as a dependency property on the outer control and, when it is updated, update the ListView's ItemsSource. But I'm not sure what type this collection should be (should I require an ObservableCollection<T>, for example), or if there are any gotchas I should look out for.
Any suggestions or advice would be much appreciated.
Thanks.

Use AddOwner to add your UserControl as an owner of the ItemsControl.ItemsSourceProperty. In the new property meta data, give a property changed callback that sets the ItemsSource of your ListView.

Related

Q: Update viewmodel property from a listview binded textbox

i've got a textbox which text is binded to a listview selecteditem as follows:
<TextBox x:Name="txtAdditional" Width="300" Text="{Binding ElementName=lstPersons, Path=SelectedItem.Additional, Mode=OneWay}" />
Now i like to implement a mechanism to add new items to the listview using this textbox to get the actual data. So i would like to bind the text of the textbox to a property of the viewmodel so it can be processed by a command.
So it the textboxes text has to be binded to the listviews selecteditem and additionally to a property of my viewmodel.
I've searched around and found some approaches but i can't help to think that there should be some simpler mechanism to archive this goal.
What I found by now:
Using MultiBindung with some kind of ValueConverter? So it seems to me that this is primary for displaying and not for updating a viewmodels property.
The use of some selfdefined custom control?
The use of an BindingProxy with in- and out-dependencyproperties like in Impossible WPF Part 1: Binding Properties?
Is there another, simpler solution to this or would i have to use one of those above?
And if one should use one of those approaches, which one whould you choose?
I can't help but thinking that this issue hasn't been given some thoughts already, using an mvvm pattern?! ;-)
yes thanks to the hint from BionicCode.
We, or better I should have to think the MVVM concept out. Of course no - or at least as little code behind as possible.
I added the property "selectedPerson" to my viewmodel and bound the SelectedItem of the listview to this property. So the object related properties were at hand directly through the "selected" object in my viewmodel and there was no need anymore to access the textbox content at all.
Thanks to BionicCode for the hint!

How to bind ItemsControl's ItemsSource property by using naming conventions in caliburn.micro correctly?

There is an ItemsControl named Items in the view and a ViewModel contains a BindableCollection<T> property Items property, I want them get binding correctly by using the naming conventions mechanism in caliburn.micro, however it dose not works as expected.
When I add ItemsSource="{Binding Items}" in the view explicitly, it works, I am wondering what's the key point missed when using naming conventions in the ItemsControl?
Firstly, using the word "Items" as a name for a property, control etc is a bad choice. It's confusing. This is true if someone is maintaining your code or reading a question. You should have considered names for things.
The conventions for caliburn micro are explained here:
https://caliburnmicro.com/documentation/conventions
Essentially, a control is examined.
The name is used to look up a property from the datacontext.
If they match then a dependency property of that control will be bound.
Which dependency property is used varies from control to control. Text is the default for TextBox and TextBlock. ItemsSource is the default for an itemscontrol.
Hence the answer to your question is your control name should match the property name.
As they seem to, this is not why your binding is failing.
You also need to provide an instance of that datacontext somehow.
You proved that is happening with your working explicit binding.
The two most likely possible causes are therefore:
Your bootstrapper isn't running the caliburn micro wireup code.
or
Your view isn't provided by the bootstrapper and you've not used viewmodel.bind on it to wire everything up.
or
You've somehow interfered with the default binding conventions.
PS
https://caliburnmicro.com/announcements/stepping-away

Generic ViewModel that works with ItemsControl

I implemented some generic CustomControls in WPF, for instance an AutoCompleteTextBox.
Now, I'd like to implement a generic ViewModel library, in order to perform the databind of these controls.
Now I defined one attached property named CDataSource, that specifies the source of the data to bind within the control.
My question is : Is it possible, that the CustomControl passes to the ViewModel the CDataSource value? In this way the ViewModel may populate the control on the basis of the CDataSource property.
Thanks in advance
This seems like a strange request to me. You don't want any dependency on your view model from within your custom control. Instead, you would normally have a dependency property on your custom control which is the ItemsSource, and then you would set the value of this from your view in XAML.
This is how the AutoCompleteBox included in the WPF Toolkit operates.

Silverlight: ViewModel trigger function in code behind

I have a bit of a problem with my Silverlight application, and my usage of the MVVM pattern.
In my View I have a DataGrid. The ItemsSource would normaly be bound to the ViewModel, but in my specific case I need the columns to be dynamic and my items collection consists of a Dictionary for each item, so I have no class properties to show. My solution was to generate all this in codebehind, since the actual design of the DataGrid has nothing to do with my ViewModel. This was the only solution I could think of since the columns can't be databound.
I have got all of this to work. My problem is that I'm using RIA and the view has no idea when the items collection has finished loading. I tried my design out by putting an ordinary button on the view to trigger the codebehind function, but obviously this solution is no good. I need my codebehind function to run as soon as my item collection has finished loading.
Can I make my codebehind listen to the ViewModel?
I have a feeling that you are messing up things somewhere.
For your question I think you can solve it by having an event in the ViewModel.
Subscribe to that event in your view's view_Loaded event and call the codebehind function in the handler.
I would recommend you to recheck your design and to see if this is really necessary.
I understand what you mean, we once had to do the same thing generating random columns which is a PIA in silverlight because you would need some kind of object that has a dynamic set of properties.
I see you've found the Dictionary solution. What I would suggest, which isn't per sé the cleanest solution but it is cleaner then putting the stuff in the code behind, is to add this in a converter. Then bind the collection to the itemssource of an itemscontrol and then when the list propertychanged is raised you assemble the datagrid in the converter.
small example:
<ItemsControl Grid.Row="1" ItemsSource="{Binding theListOfEntities, Converter={StaticResource theconverter}}"/>

working with WPF usercontrol and MVVM

I have following questions
Should the consumer of my usercontrol assign the usercontrol's DataContext or set some dependency property. (related to #3 : if DataContext then my individual items need to bind directly to the object given in DC, if DP then I have the luxury to have bind to any VM)
If they set property, and if I am using 3 primitive items, should I accept them as individual properties or combine them together to a Model for my usercontrol
Should I ask the consumer of my usercontrol to send me model or viewmodel ( I say viewmodel but for all the controls I have used so far, I have never seen anybody asking me to send them VM - I am sure some could be implementing MVVM internally
Your consumer wants a user control. So I presume the user control should be able to work in any context/application(WPF). So, to answer your questions
1) The consumer should set dependency properties which is defined in the user control. By using the datacontext you will be coupling the usercontrol to the consumer.
2)Take them as individual primitive properties, otherwise the consumer needs to create an object unnecessarily to cater with your model(coupling again-why should the consumer need to know about your model?).
3)No, you should not ask the cosumer to send you the view model.Why do you need to know which consumer is using your "generic" user control.
If you cannot do any of the above because of practical considerations - then dont worry about breaking any/all the rules because your user conrol is coupled with a specific context-it is not generic any more. If you write a generic user control, any WPF application can use your user control. It is your call.
1.
I would say this depends on the kind of UserControl, if it is "generic" you should be able to change the DataContext as the control internally should not have anything to do with the DataContext. For example if i create an ImageButton UserControl which exposes the properties Caption and ImageSource then those should be bound internally independent of the DataContext, the on the instance those can be bound and the DataContext may be changed as well, e.g.
<uc:ImageButton Caption="{Binding ButtonInfo.Caption}"
ImageSource="{Binding ButtonInfo.Image}"/>
Here one could then change the DataContext to simplify the bindings a bit:
<uc:ImageButton DataContext="{Binding ButtonInfo}"
Caption="{Binding Caption}"
ImageSource="{Binding Image}"/>
If on the other hand the UserControl is a view for a viewmodel i would expect the UserControl to bind to viewmodel properties internally, relative to the DataContext.
So in a DataTemplate where the current DataContext is already the viewmodel of that view a simple instance without anything should do, i.e.
<v:StatisticsView />
If the viewmodel to be passed is in a property of the current DataContext you may bind the DataContext as well:
<v:StatisticsView DataContext="{Binding StatisticsViewModel}"/>
2.
This can be handled either way i would say, especially if you have only three properties its not too much of a hassle to create those. You might want to consider some aspects like dependency, e.g. does it make sense to group all three propeties in an object?
3.
As noted in 1. this should be apparent from the UserControl itself, if it's a StatisticsView the consumer should pass in a StatisticsViewModel (either implicitly by inheriting the current DataContext or by binding it explicitly).

Resources