Passing control as command parameter in Silverlight and MVVM Light - silverlight-4.0

I am trying to get my head around MVVM and the Navigation-based project template in SL4. At the moment I am trying to move the ContentFrame_Navigated event handler into the ViewModel. Basically this event handler checks each hyperlink button in the menu bar against the current page and adjusts the style accordingly. To do this it seems I need to pass the EventArgs as well as another object. I see MVVM Light has the PassEventArgsToCommand bit, but what about passing another object/control? In this case it's the StackPanel hosting the list of menu item hyperlinks. I'm just getting my head around the MVVM concept, what's the best practice in this case?
Cheers,
Dany.

With MVVM you have to think more abstract. You are not daling with a list of HyperLink elements, but with a list of Navigation Targets. I.e. you should separate the presentation (HyperLink elemen) from the data (the URL, the Title, whether the item is selected or not, etc.). You now hold the data in a list on your ViewModel (normally you would see this data as the ViewModel of your Hyperlinks, and name it accordingly). The items are held in a ObservableCollection so that you can track changes if a item is added etc.
To display this list you can use a class inheriting from ItemsPresnter (e.g. a ListBox) and use binding to set the properties. Now you navigate to a page you can set the IsSelected property of the relevant item in the list, resetting all other IsSelected properties.
As the navigation targets can be seen as a global collection, you can also hold it in a property on the ViewLocator, so that all Views and ViewModel can access this list, and setting the IsSelectedProperty is applicable to all Views. This global collection represent you navigation state.
And, BTW, the EventToCommand, the RelayCommand, and the Command attribute ony support one parameter. Furthermore, from experience I can advise you that it is not good practice (although you obviously can do it) to mix View objects, such as EventArgs, or elements and your ViewModel.

one solution is to put the menu items the ViewModel, and the View can bind this list.
then the View wouldn't need to send the menu items to the ViewModel

Related

Clicking on an image in a collection view

I have a collection view and each item has an image and a label. I want to click the NSCollectionViewItem or NSImage and then hide the collection view and display a completely separate view containing the details of the object that was clicked.
I cant find any documentation on how to handle click events in this situation. How is this possible? I have built out the collection view in Interface Builder so everything was done via bindings as opposed to code.
#Jeff, I don't have permissions to add a comment so writing this as answer.
You can overwrite setSelection in your subclass of NSCollectionViewItem (as explained by #indragie in Selection Highlight in NSCollectionView) to track the selected item and perform an action.
The solution that I went with was to not actually use an Image Well, aka NSImage. I used a button and bound the Image property to an instance of an NSImage that I exposed as a property on my model.
It was easy enough but I'm shocked more people havent been asking this question.

How do I bind UserControl to GridView while grouping?

I want to Bind UserControl in the ItemTemplate section of the GridView.
UserControl contains nothing but with decorated text..
I had been using Collection which consisted of and was binding Content directly within ItemTemplate within the main xaml page, which was easy.
But now my collection is changed to .. How do I bind now?
Don't put UserControls in the model (i.e. your collection). They belong in the view (i.e. your XAML page).
I'm guessing you replaced the String you used originally with a UserControl because you want to use a different UserControl for different items. Take a look at ItemTemplateSelector. You can bind it to a DataTemplateSelector inside which you can decide which template to use based on the individual item. You can now have a custom class for the Content and a property inside it to select the UserControl based on it.

NSPopUpButton + Bindings + Show All Option

I'm trying to develop a NSPopUpButton that will serve as a filter to some datasource, let's say a NSArrayController that fills a table.
I can bind the NSArrayController from the menu to the selection keypath so the data is properly filtered, no problem with that.
Tricky part is, I want the content of this NSPopUpButton to rely on an NSArrayController using bindings, but I'd like to add a "Show All" menu item, or at least some item that doesn't come from the Core Data and performs some special action other than filtering the table using bindings and core data.
I'm trying to perform something like the NSPopUpButton used by finder in the filter bar, the last item of the menu performs a special action, while the others just filter the result.
I understand that the approach is to forget about bindings and do it everything programmatically, because I believe there's no way to mess up with the NSArrayController and bindings to add this custom menu item that doesn't rely on core data, but since I haven't found anything on the Apple Docs and here, I'd like to share my thoughts... any ideas?
sounds to me like you're looking for the NSContentPlacementTagBindingOption.
you edit the NSMenu that's attached to the NSPopupButton as follows
you then edit the settings on the NSMenuItem you want to have replaced with your array controller contents so that it has a meaningful tag associated with it
you then specify that tag as the content placement tag value on the NSPopupButton's bindings for the content/content* bindings.

Changing visibility of NSPopUpButton's items based on keypress

I've got an application here that needs to read in a bunch of data from an external file and display it as a NSPopUpButton in a Cocoa user interface. The catch here is that the data that is being read in needs to have a flag that states if it is considered "hidden" or not.
If the data is hidden, it needs to be added to the NSPopUpButton as an NSMenuItem, but the hidden flag needs to be set to YES so it does not normally appear in the NSPopUpButton menu. If the user holds down a "magic key" on their keyboard (usually ALT, in this case) then those hidden objects need to be unhidden. If the user lets go of the ALT key, then they need to be automatically re-hidden, except for the one that may have been selected -- which would become hidden if another NSMenuItem were chosen.
I'm kind of having a heck of a time figuring this out, actually.
I was wondering if there is a straight forward way of doing this using NSArrayController and an NSPopUpButton, but thus far I have not been able to find anything resembling a solution -- not when it comes to managing the hidden property of the NSMenuItem objects.
Does anyone know how this can be achieved using Cocoa Bindings?
You can wire the popup to an array controller and alter the filter predicate. From an MVC design standpoint, you wouldn't use an attribute like "hidden", which is a view characteristic, but maybe "advanced". Normally, set a filter predicate on your array controller to "advanced = no". Then when the user holds your preferred modifier, remove the predicate. The popup will update automatically. The array controller should be bound to an array property on another object (in your data model). The popup should be bound to arrangedObjects on the array controller.

Xaml Dynamic Grid with Viewmodels

Hello i am trying to create a grid in xmal that is populated via a ViewModel.
The grid is a 5x5 grid, and my ViewModel contains a list of "MyObject". This object contains 2 int variables Row and Column witch indicates where in the grid the Object should be.
MyObject is also a view models, and the grid space should be filled with Data Template names MyTemplate with the MyObject as the DataContext.
Now I pretty new to xaml and view models, but how would the best way of doing the be?
Let's see...
Put an ObservableCollection into the VM, then...
Option 1:
...a simple Grid into V. Subscribe to it's CollectionChanged event from xaml.cs, add ContentControls for each Added object to grid, bind the ContentControl's Grid.Row and Grid.Column property to each object's properties, and set the DataContext to the object itself and ContentTemplate to Resources["MyTemplate"]. (Also, for any removed objects find the corresponding ContentControl and remove it.)
Pro: easy
Con: .cs, no designer support
Option 2:
...an ItemsControl into V. Set its ItemPanelTemplate to a Grid, and bind your ObservableCollection to its ItemsSource. Then set your Itemtemplate to MyTemplate. Now, the trick is to make the items put in the correct cell, based on your values. For that, use the ItemsControl's ItemContainerStyle property, and bind the container's Grid.Row and Column to those properties.
Pro: nice xaml and easily extended
Con: ItemContainerStyle is tricky in WPF and missing in Silverlight, so in case of the latter, you can forget it
Option 3:
...a custom panel which you write. Inherit it from Grid perhaps. Than if an element is put into it, check if it's DataContext implements an interface which contains your properties. Then use this as an ItemsPanel in Option 2...
Pro: it should work perfectly
Con: You have to write a new Panel for this...
Hopefully one of these 3 will be ok for you.