Multiple Selection Combobox - silverlight

I have a scenario where there is a combobox with checkboxes, so multiple selection is possible. After selecting the combobox items, I need to execute an update query. I know to write the query for single item, but how to do the query for multiple selections from combobox.
Regards,
Raghu

The combobox shows items based on a list of view models, lets name them CheckableViewModel in the view model that is the data context of te view:
class ViewModel
{
//...
List<CheckableItemViewModel> Items;
//...
}
<ComboBox ItemsSource="{Binding Items}"
<!-- more properties --> />
As far as querying data is a task done in the data logic this task has also to be triggered there. This means that your CheckableItemViewModel has to signal a change of it's checked state, e.g. via an event (at least PropertyChanged on property Checked). The view model that contains the list of CheckableItemViewModels, which is the view model the UI binds to, has to listen for this event. And this view model has to contain the logic to call the appropriate query containing the appropriate data.

Related

Two ListViews with different filters on the same data set

I have a ViewModel with some ObservableCollection _questions, which is loaded from DB when VM instance created. Also this list is used to collect data to save back to DB.
This Vm is used for a View1 and it displays the list in ListView with filtering by a property using CollectionViewSource.GetDefaultView(_questions).Filter = ...
Now I need to create View2 which will display same list but without filtering.
I can't bind it to the same ObservableCollection _questions because it has filter defined on CollectionViewSource, but I need to use it to keep SaveToDb code same.
Is it possible to have different filtering on the same data source for two different ListViews?
I have never enjoyed using CollectionViewSource. I would instead filter using a new property in my ViewModel that filters using Linq:
public IEnumerable<MyType> FilteredItems()
{
get
{
return MyCollection.Where(x => x.MyProperty == SomeValue).ToArray;
}
}
I would then bind ItemsSource to this property and use INotifyPropertyChanged event to notify UI of changes to the collection.
Its hard to tell if this fits your scenario well as there is not much information provided on what you need to achieve.

How Bind Child Control To A View Object (Like PageCollectionView) In Master\Detail scenario With MVVM In SILVERLIGHT

I have a question about “Master\Detail” data binding using MVVM and I hope you can help me with it:
Let say my Master ModelView is “ProductModelView” (for Product Entity) and the Product Entity has a property named ProductInventories of type Entity Collection. I defined a “DomainCollectionView” in my master ProductModelView with name: “ProductViewDCV”
I do following items to fill my master and details Datagrids:
1-Set the DataContext of my page to my ModelView : ProductModelView
2-Bind master Datagrid (name: masterDG) to ProductViewDCV.
3-Bind detail Datagrid (name: detailDG) to ProductInventories property of my master ProductViewDCV :
<sdk:DataGrid x:Name=" detailDG "
ItemsSource="{Binding Path= ProductViewDCV. ProductInventories }"/>
The Program works well ,As I change the row in master DataGrid , The current item in the child DataGrid also changes.
But my question and Problem :
When I bind my detail (child) DataGrid as mentioned in step 3 , the child DataGrid is bound to “EntityCollection” not a View Object Like “PagedCollectionView” or “DomainCollectionView” ,So I can’t use benefits like Sorting ,Grouping and Paging on my child (detail) DataGrid. I want to know :How I can bind my child DataGrid to a View Object in MVVM pattern to use Paging option.(Namely I want to have Paging and Grouping Options in my child DataGrid.)
Look forward to receiving your reply.
Hello.
I really appreciate your kind and quick answer. I did as you said ,but I encounter a problem and I hope you help me:
Method:
In my “ProductModelView” (for Product Entity) I defined following objects:
1-private DomainCollectionView _ProductViewDCV; (As Master(Parent) View)
2-private PagedCollectionView _ProductViewPCV; (As Detail(Child) View)
3-In Constructor of “ProductModelView” class, I assigned an EVentHandler to “_ ProductViewDCV”(my DomainCollectionView as Master view):
this._ProductViewDCV.CurrentChanged+=_ProductViewDCV_CurrentChanged;
this._ProductViewDCV.Refresh();
4-In the EventHandler , I Create a new “PagedCollectionView” (my Detail/Child view) and assign it to my _ProductViewDCV :
if (_ProductViewDCV.CurrentItem != null)
{
_ProductViewPCV = new PagedCollectionView((_ProductViewDCV.CurrentItem as BA1.Web.Product).ProductInventories);
//ProductViewPCV.Refersh();
}
5-In my View File (XAML file), I have two Datagrids which are configured as follow :
Page DataContext is set to an object of my ModelView : ProductViewModel
sdk:DataGrid x:Name="dgParent" Grid.Row="1" ItemsSource="{Binding Path=ProductViewDCV}"//my Master/Parent DataGrid
sdk:DataGrid Grid.Row="2" x:Name="dgDetails" ItemsSource="{Binding Path=ProductViewPCV}//My Detail/Child DataGrid
Problem :
When I change the current row in my Master/Parent DataGrid , nothing happens in Detail/Child DataGrid and testing the Detail/Child DataGrid’s Itemssource property , returns “Null” ,not an object of “PagedCollectionview”.
Where’s my problem and why doesn’t the Detail/Child DataGrid get updated in response to Master/Parent current item changing? (Testing shows that ProductViewPCV itself changes when it’s parent collection changes.)
Again let me thank you for giving me advices on this problem.
Off the top of my head, there's a few problems I can see. You should instantiate the _ProductViewPCV PagedCollectionView property in the constructor, and not create new instances of it in the _ProductViewDCV_CurrentChanged event handler. If you did want to do this, then you need to notify the view that the value of this _ProductViewPCV property has changed by raising a PropertyChanged event. However, you shouldn't do this as it's likely to result in a memory leak.
You'd be best off wrapping an observable collection in the PagedCollectionView, and simply updating the contents of the observable collection in the _ProductViewDCV_CurrentChanged event handler I think. The view should update automatically I think. Sorry, I'm a little rusty on this, but I think that should work for you.

Creating a dynamic seach using MvvM and WPF

I am fairly new to mvvm and WPF so I am looking for some pointers to achieve the following.
I would like to create a search section in my app that builds up the search options based on whatever the users selects as their criteria.
So for example the first combo box of the search offers the top level of choices:
Date of Message
Gateway
Direction
Etc..
......
The second section is my operator
So, for example if Date of Message is selected then the user is offered another combo box of choices
Is Between
Last Week
Last Month
Etc..
The last section of the search is based on the operator above, so if Is Between is selected the form displays two Date Pickers from and to. If on the other hand Last Week is selected then nothing is displayed as the search can directly call my SetActionLogsForLastWeek() method once I click my search button.
If the user selects Gateway from the initial list then another combo box is build with a list of choices based on gateways.
I am looking for a tutorial or previous post that points me in the right direction on achieving my goal of building WPF elements based on selection choices from other elements.
Thanks
This is a rather extensive question, and as such there is no definitive answer. I will describe how I would handle this problem. Keep in mind that this might not be the best solution out there.
In order to render the controls which depend on the first combo box use data templates and distinct view models. In the resource section of your main view, or an external resource if you have defined one, write something like this:
<DataTemplate DataType="{x:Type vm:YourViewModel}"> <vw:YourView /> </DataTemplate>
You will have to import the namespaces containing your viewmodels and views (vm: and vw: here). Using content-controls you can render views depending on their viewmodels:
<ContentControl Content="{Binding CurrentViewModel}"></ContentControl>
In your code behind, you will have to have a ViewModel which you can bind to. Depending on the selection of the first combo box, you can now swap out the ViewModel in the code behind in order to render the dependent combo boxes - or nothing at all!
In order to illustrate, let me provide some sample code. Lets start with you main view model. Thats the one containing the collection the first combo box binds to (e.g. the strings "Date of Message","Gateway"...)
public class MainViewModel : BaseViewModel {
public IObservableCollection comboBoxItems;
public BaseViewModel ControlViewModel {get; set;}
private String selectedItem;
public String SelectedItem {
get {
return selectedItem;
}
set {
selectedItem = value;
OnPropertyChanged("SelectedItem");
ChangeControls();
}
}
private void ChangeControls(){
switch(selectedItem):
//swap out the control view model here e.g.
controlViewModel = new GateWayControlViewModel();
}
}
Btw, BaseViewModel is an abstract class which all view models inherit from. It implements INotifyPropertyChanged.
In your main view it is enough to have content control binding to the control view model, as well as the first combo box:
In your resources.xaml you define the data template, as discussed before.
<DataTemplate DataType="{x:Type vw:GatewayControlViewModel}"> <vw:GatewayView /> </DataTemplate>
This will render the GateWayView if the ViewModel, which the ContentControl in the main view is bound to is equal to GateWayControlViewModel. Finally, your GatewayView could look like this:
<ComboBox ItemsSource="{Binding Gateways}"
SelectedValue="{Binding SelectedGateway}" />
Obviously, you will have to make sure your GatewayControlViewModel actually contains the items and properties mentioned in the view. It will also need to derive from BaseViewModel.
I hope this gives you some ideas. Additionally, you might find this link useful (as it contains some very useful tips on how to approach MVVM).
If you want to implement Search in Collections for example in as in Combobox or Grid you should read a bit about ICollectionView. The ICollectionView will allow you to filter collection based on your search criteria. In your example you can also do this by handling selection changed events at the viewmodel and create method to update your data based on selected inputs.

How to bind to a method on ViewModel with data from View

I currently have one view with 3 fairly simplistic view models. For the sake of this discussion, we will focus on 2 of the three view models.
The View is a User Management user control. It contains a DataGrid that has its ItemsSource binding set to a UserListViewModel. This view model simply displays user information in the data grid.
The User Management View also contains some other controls, such as buttons for adding new users and removing users. Those buttons are currently bound to a second view model called UserManagementViewModel. For example, the Remove button will successfully call the RemoveUser method on the UserManagementViewModel.
My question is, via XAML (as I hate code-behind), how can I pass the SelectedItem property of the DataGrid (bound to UserListViewModel) into the RemoveUser method call on the UserManagementViewModel? I realize that, in the MVVM design pattern, my view model can't look into the view to retrieve the information necessary, so there must be a way via binding to pass that information into the method.
XAML code examples (or links that show how) to perform similar functionality would be appreciated. Thanks for any help!
you can simply use a commandparameter
<Button Command="{Binding RemoveCommand} CommandParameter="{Binding Elementname=gridUser, Path=SelectedItem}" />
or your UserManagementViewModel have access to the UserListViewModel then you need a command without commandparameter and simply use the SelectedUser property of your UserListViewModel instance
public void ExecuteRemove()
{
var userToRemove = this._myUserListViewModelinstance.SelectedUser;
...
}
I believe what you seek is commanding with a command target bound to the datagrid's selecteditem where one can route such information from the datagrid; say when a button is pressed.
See Commanding Overview on MSDN

"Nested" MVVM Question

I have a WPF window that has a datagrid and a user control for a form for the fields in that datagrid. The user control and the WPF window have view models.
The user control's DataContext is bound to one of the window's view model's member field, whose value changes during the data grid's Selection Changed event.
I'm not sure if this is the right way to do it because I am unable to create references from the inner view model to the outer view model for some reason. Constructor injection won't work because I'm required to use default constructor only, and I can't seem to put a property injector in the right place (always getting null reference when I try to use it).
I am also unable to get my property change notification to work properly in the inner view model.
Is there a better way to wire my view models so that they automatically change the values in the user control when a new row is selected in the datagrid? I have a feeling that binding to the control's DataContext is not the way to go.
This doesn't seems a complex/nested scenario. Looks like pretty much a normal master details scenario. Suppose you want to edit Customer data, I would have an ObservableCollection instance bind to the DataGrid, and there will be a SelectedCustomer property in the VM also. In the DataGrid you can set SelectedItem twoway bind to the SelectedCustomer property which makes SelectedCustomer always updated with your selection. Since the usercontrol has the same instance of customer as in the DataGrid row, whenever you change anything in the UC those data will get reflected in the grid. Ofcourse all those properties should fire NotifypropertyChanged.

Resources