Silverlight: ViewModel trigger function in code behind - silverlight

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}}"/>

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!

Presort Silverlight DataGrid in MVVM

I'm binging DataGrid to ObservableCollection I update collection on timer and grid updates nicely which is what I want.
However, even though I can sort collection on initial population - when I append new items they go to bottom. User can sort grid and then it looks good.
I would like to "force" grid to sort by specific column when it is initialized. Can it be done in XAML or somehow in MVVM manner?
EDIT
Just to give more details. This is mail client main screen. I've got service that polls for data and if new mail arrived - it get's appended to collection. Sorting at this point is not desirable for couple reasons. First, this is list of object. Second, user may decided to sort by other column using DataGrid
It feels right to set grid to sort by column I initially want (Time Received) and let users sort by any column while preserving this order when new items arrive.
You should wrap your ObservableCollection in a collection view. Generally you will wrap the collection in either a CollectionViewSource, or a PagedCollectionView. The CollectionViewSource can be used declaratively in XAML, but can't be controlled from the ViewModel. You can however wrap your collection in a PagedCollectionView, and expose that from your ViewModel. This MSDN article should help you: http://msdn.microsoft.com/en-us/library/dd833072(v=vs.95).aspx. Collection views are very powerful tools, and will help you elegantly bridge the gap between a View and a ViewModel. Hope this helps.
[Edit] Edited the answer to correspond to the solution
You can try adding SortDescriptions by including the Collection in a collectionView. In example.
<CollectionViewSource Source="{Binding ObservableCollection}" x:Key="Data" >
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="City" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
Then in your ItemsSource set the following binding.
ItemsSource={Binding Source={StaticResource Data}}
Just sort inside your ViewModel, where ever you're updating the collection from the timer sort it. In fact when you sort the collection the view should rebind if you're binding correctly in the View/Xaml to the datacontext(the viewmodel).
Anytime you update an Observable collection in a viewmodel anything that's bound to it will be updated.

WPF events, commands or using both

I am constructing my app infra structure, and finding it hard to achieve a very basic behavior - I want to raise events from different user controls in the system and being able to catch those events on some other user controls that listens to them. For example i have a user control that implements a TreeView. I have another user control that implmements a ListView. Now, i want my ListView to listen to the TreeView, and when the selection is changed on the TreeView, i want to repopulate my ListView accordingly.
I also want this to happen even if the ListView is not located within the TreeView on the WPF logical tree.
PLEASE HELP!!
Thanks,
Oran
Use data binding.
If the content of the list view is stored inside the object shown in the tree view you can just bind into the tree SelectedItem property.
Otherwise bind the tree SelectedItem to a property in your view models (or your window!) and in the setter of this property change the list that is bound to the list view ItemSource property.
You can see the technique in this series on my blog the post I linked to is the last post with the code download link, you'll need to read from the beginning of the series if you want the full explanation.
EDIT: Here's how I did it in one project: (the GridView definition removed since it's not relevant here)
<TreeView
Name="FolderTree"
Width="300"
ItemsSource="{Binding Root.SubFolders}"
ItemTemplate="{StaticResource FolderTemplate}"/>
<ListView
Name="FileView"
ItemsSource="{Binding ElementName=FolderTree, Path=SelectedItem.Files}">
</ListView>
The list bound into the tree view's ItemsSource is of objects that have 3 properties: Name (that is bound to a TextBlock in the FolderTemplate), SubFolders (that is likewise bound to the HierarchicalDataTemplate.ItemsSource property) and Files that is bound to the ListView using {Binding ElementName=FolderTree, Path=SelectedItem.Files}
Note that non of the lists are observable collections (because in this project they never change) but are loaded lazily (on-demand) by the properties getters (because in this project they are expensive to load).
This is the point where the added complexity of MVVM (Model-View-ViewModel pattern) can start to pay off. What you need is a publish/subscribe infrastructure, and MVVM Light has that, along with good MVVM structure that doesn't get overly complex. Prism is another good WPF/Silverlight infrastructure foundation with publish and subscribe support.

Best practice for forwarding ItemsSource

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.

MVVM What is the way of updating a UI after a command?

I'm learning MVVM through a project and I got stuck on something simple.
I have a Button that updates a ListView. I have a command in the ViewModel that make the right things but I want to select the new row and get the focus on a TextBox after I click the Button.
The question is: How do I update my UI after executing a command?
If I need to change my windows Title when an operation have been made, I use a property on the ViewModel that is binded to the Window's title and it's changed when I need it but, I don't know how to get focus on a control when a command has been executed.
Thank you.
To select the new row, add a new property to your ViewModel ("SelectedItem" for instance), and bind the ListView's SelectedItem property to it :
<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">...
In the ViewModel, you just have to assign the new item to the SelectedItem property
To focus the TextBox, Mike's idea seems a good one
You could make an attached behavior. I'd suggest using the new Blend behavior framework, ie TriggerAction that contained this custom logic.
For your attached behavior you put on the button, give it a DP for an ICommand and maybe a DP of a ListView type.
On the "protected override void Invoke(object parameter)" of your TriggerAction, execute your ICommand, then you have reference to your ListView. Here you can do your custom code on it, like setting focus.
Your XAML may look something like this:
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Behaviors:CustomBehavior Command="CommandName" ListView="{Binding ElementName=myListView}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Button/>
I suggest looking at Mike Brown's ExecuteCommandAction behavior (download here), it's about almost 1/2 of what you need.
What about setting focus to the control in the code behind: textBox.Focus()
I consider everything you mention in your question to be GUI logic so I would add a Click event to the button to handle stuff that needs to happend in the GUI.
Hope this helps.
I think you need to use the Mediator pattern. Please see this:
Josh Smith's Mediator Prototype for WPF Apps
This is generally used in communicating with the View from the View-Model. Hope this helps.
In your case you need some way that the ViewModel notifies the View that it should set the focus on a specific control.
This could be done with an IView interface. The view implements this interface and the ViewModel can call a method of the View over this interface. This way you have still the View and ViewModel decoupled of each other.
How this can be done is shown here:
WPF Application Framework (WAF)
http://waf.codeplex.com

Resources