I have setup the project integrated the data source with DevForce, and now I need to decide on a navigation framework for the test. I think a tab approach would be best. Does your tab control play well with MVVM? If so do you have any samples or guidance? Or is there a better control you have to manage the views?
9 Answers, 1 is accepted
Thank you for considering our Silverlight controls suite. Currently we are not aware of any existing problems between RadTabControl and the MVVM pattern. My suggestions is to go through the following articles:
RadTabControl's help page
How to: Telerik’s TabControl for Silverlight
Tab control and prism
There are also tons of useful information in our forums, so if you encounter any issue, don't hesitate to contact us. We'd be glad to assist you.
All the best,
Kiril Stanoev
the Telerik team
It would be helpful to be able to see a sample. Or to put it another way, if I were to review the prism sample listed, what changes would need to be made to use it with mvvm light instead?
You can find the attached example project of RadTabControl with MVVM Light. However it is simple, can give you good insights on how to use it.
I'll work on it to make it more complete, so if you have any specific problems and solutions you want to see - please go ahead and share them with us.
Thank you for your collaboration.
Miro Miroslavov
the Telerik team
In code behind
private void MainMenu_ItemClick(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
RadMenuItem item = e.OriginalSource as RadMenuItem;
if (item != null)
{
switch (item.Name.ToString())
{
case "Customers":
RadTabItem rtiCustomers = new RadTabItem() { Header = "Customers", Content = new CustomersView() };
tabControl.Items.Add(rtiCustomers);
rtiCustomers.IsSelected = true;
break;
case "Customer":
RadTabItem rtiCustomer = new RadTabItem() { Header = "Customer", Content = new CustomerView() };
tabControl.Items.Add(rtiCustomer);
rtiCustomer.IsSelected = true;
break;
case "Manufacturer":
RadTabItem rtiManufacturer = new RadTabItem() { Header = "Manufacturer", Content = new ManufacturerView() };
tabControl.Items.Add(rtiManufacturer);
rtiManufacturer.IsSelected = true;
break;
etc.. }
and in xaml this is the key stuff
<
telerik:RadMenu
x:Name
=
"MainMenu"
ClickToOpen
=
"False"
ItemClick
=
"MainMenu_ItemClick"
VerticalAlignment
=
"Top"
HorizontalAlignment
=
"Center"
Grid.Row
=
"0"
Grid.Column
=
"1"
>
<
telerik:RadMenuItem
Header
=
"Manufacturers"
>
<
telerik:RadMenuItem
Header
=
"List"
Name
=
"Manufacturers"
>
...
and
<
telerik:RadTabControl
FontSize
=
"15"
x:Name
=
"tabControl"
Margin
=
"10"
Grid.Row
=
"1"
Grid.Column
=
"1"
>
<
telerik:RadTabItem
Header
=
"Home"
/>
</
telerik:RadTabControl
>
The next step would be to move the entire switch statement to its own method, and call it from the MainMenu_ItemClick . That way other sources of new new tabs could call that same method. A simple change.
The next step in making this tab system work is a close tab function that releases the view and closes the tab. The trick is it needs to be triggered by the view in the tab, messaging back to the mainpage. If you know how to do that, which I am sure you do, a sample of how to structure the messaging would be helpful. Somehow the mainpage needs to know which unique tab wants to be closed, since more than one can have the same name and type of content. i.e. there can be more than one order open at a time...
One more question, which approach do you prefer, mine or yours, and why? I am just learning all the mvvm stuff, so the why is important to me.
private void MainMenu_ItemClick(object sender, Telerik.Windows.RadRoutedEventArgs e)
{
RadMenuItem item = e.OriginalSource as RadMenuItem;
if (item != null) CreateTab(item.Name.ToString());
}
private void CreateTab(String tabname)
{
switch (tabname)
{
case "Customers":
RadTabItem rtiCustomers = new RadTabItem() { Header = tabname, Content = new CustomersView() };
tabControl.Items.Add(rtiCustomers);
rtiCustomers.IsSelected = true;
break;
case "Customer":
RadTabItem rtiCustomer = new RadTabItem() { Header = tabname, Content = new CustomerView() };
tabControl.Items.Add(rtiCustomer);
rtiCustomer.IsSelected = true;
break;
case "Manufacturer":
RadTabItem rtiManufacturer = new RadTabItem() { Header = tabname, Content = new ManufacturerView() };
tabControl.Items.Add(rtiManufacturer);
rtiManufacturer.IsSelected = true;
break;
default:
RadTabItem rtiDefault = new RadTabItem() { Header = tabname, Content = "Not defined yet, TODO!! Add this tab to CreateTab in MainPage.xaml.cs" };
tabControl.Items.Add(rtiDefault);
rtiDefault.IsSelected = true;
break;
}
}
We will need more time to investigate and provide you with a proper reply. We will let you know very soon.
Greetings,
Kiril Stanoev
the Telerik team
Your approach is more the Win Forms style than MVVM. It is working and it's fine, but with the MVVM - you'd more likely doesn't have code-behind. Rather all the functionality is exposed from the ViewModel via Properties and Commands. You can examine the example that I've send you. It uses all the MVVM approaches like Commanding, Binding and Messaging. The messaging is the way the ViewModels are communicating - and in the example each tab send message to the TabsViewModel that should be closed.
I hope I'll have time soon to describe this thoroughly in a blog post.
Miro Miroslavov
the Telerik team
I have been reading a number of blog entries about MVVM and the issue of whether you should use code or not. My tfeeling is that is makes sense to use code when the code is managing UI and it logically belongs, but not if its executing business logic or affecting data. So I don't see an issue with managing the binding of views to tabs in the code, or even listening for the close request there. The close itself might not come from a control, so messaging might make more sense than commanding. For example when a user executes a save and exit button, I will need to execute a command in that viewmodel, and at the end of that command, send the close request back to the main view. There also are circumstances when as part of the business login in a viewmodel I might need to add or delete a tab, or even change the focus. In all those cases I will need to communicate messages back to the mainviewmodel to make it happen. Can that be done with commanding, or is it more suited to messaging?
The way I understand it, the view manages UI, the viewmodel links the view to data and takes care of business logic, and some of that should be torn off and put in a number of repositories to put further insulate the data and business logic. Code behind lets you do dynamic things with the UI without being a contortionist (bending in unnatural ways just to avoid coding). Although I am a complete newbie, I believe keeping things simpler has a virtue, even if its not as cool
In the MVVM world the answer "It depends" for everything is getting huge popularity these days, because it really depends on how you want to structure your application. If it is up to me - I'll go for commands everywhere I could and leave the messaging in only those cases where I can't use easily RelayCommand (DelegateCommand).
The reason you shouldn't use the code-behind (View) for creating something or binding... is that you can't test the code-behind easily with Unit tests and also the so called "separation of concerns".
In the perfect world the ViewModel should keep the state of the UI and expose to the View the needed functionality thought Commands (they are also good for testing, because they could be executed by code...).
The View is doing nothing but binding to the states and commands of the ViewModel.
Your Business Logic is in the Model (or Services) and the ViewModel wraps it. So you don't have Business logic in the ViewModel.
Anyway the world isn't perfect, so sometimes you should write code in the View that for example is managing the Focus, TabSelection or any other really close connected functionality of the View itself.
I hope this will help you clarify the idea behind MVVM.
Miro Miroslavov
the Telerik team