Reputation: 623
I am new to MVVM model. I have an user control with number of buttons. I am handling the click event of these buttons in the view model class through the RoutedEvent. I have to call/open another user control in the click event of a button. How to achieve this?
Thanks in advance...
Upvotes: 2
Views: 1910
Reputation: 308
To do what you want to do, you'll want to use a combination of controls and forms. Please note, my answer is applicable to Silverlight 4 and up. First of all, i would bind the button "COMMAND" to a view model command implementation. In the following example, my control's DataContext is an instance of my view model. My ViewModel implements a hash table of a set of Keys(strings) and ViewModelCommand classes. Ignore the complexity of the implementation. The point is the Button is bounded to a "COMMAND"
<Button Style="{StaticResource stTitleButton}" Height="Auto" Foreground="White"
Command="{Binding ViewModelCommandIoC.ViewModelCommands[FIND]}"
CommandParameter="{Binding ElementName=enHiddenControl}"
Visibility="{Binding CanSwitchCustomer,Converter={StaticResource VisibilityValueConverter},FallbackValue=Collapsed}"
>
In the example above, the command is bound to my command indexed under "FIND". It's the same as just binding directly to a command. The next important piece is the CommandParameter. This is a hidden instance of the control that you wish to show in a new window. The name of the control in this case is 'enHiddenControl'. You may place this control anywhere on your screen, just make sure its hidden. This will come in as the parameter in the method signature of the command. For example:
/// <summary>
/// Finding an existing customer
/// </summary>
/// <param name="sender">The command parameter - control </param>
/// <param name="e"></param>
public void OnChangeCustomer(object sender)...
When this sender comes in, the goal is to get the type and use the activator to create an instance of that class. The Activator is found in System.Reflection or System.Reflection.Emit. (I'm typing this from the top of my head and it's primarily theoretical, but should work ;)
Activator.CreateInstance(sender.GetType())
Once you create an instance of this class, add it to the LayoutGrid on a "ChildControl". How? Create a grid, name it "LayoutRoot". Create a ChildControl, add the grid to the child control, then add the instance that you just created to the grid. Show the form. Theoretically, you've just dynamically created a form with your control without knowing about specific classes. Only generics. The sizing of the form....that's another story. I would use Auto for both width and height. And the size of the control should as a result, theoretically dictate the size of the form.
At the end the method should look something like this:
public void OnChangeCustomer(object sender)
{
//the search screen
if (sender is UserControl)
{
UserControl uc = Activator.CreateInstance(sender.GetType()) as UserControl;
Grid grdLayoutRoot = new Grid();
grdLayoutRoot.Name = "LayoutRoot";
grdLayoutRoot.Children.Add(uc);
ChildWindow cw = new ChildWindow();
cw.Content = grdLayoutRoot;
cw.Show();
}
}
All of this is THEORETICAL and have never been tested, but it should work, given the amount of times I've pulled stunts of these sort of nature in C#.
Upvotes: 0
Reputation: 10306
What you describe is one of the problems most people new to MVVM struggle with - Navigation. I'm trying to avoid in general to have any of my Viewmodels bear any knowledge on neither its own view (a viewmodel is supposed to be pretty view agnostic) nor any other view.
One way to solve this is to have a central component in your application that handles all navigation. Let's call it NavigationController. This component handles navigation requests and is responsible for creating the views (and optional the associated viewmodels) and their initialization and it is the only component in the application that really knows about the interdependencies between the various ViewModels and their respective views.
Ideally the communication between ViewModels and the Controller is performed through an Event Aggregator (TinyMessenger for example) which makes it easy to implement a loosely coupled navigation (and much more).
As a final remark I doubt that you meant that you want bring up a simple UserControl but rather some kind of dialog which would mean a UserControl hosted in a child window. This can be solved using the approach I've outlined as well.
Upvotes: 3
Reputation: 1979
Either you put the control in the XAML with the visibility property set to collapsed and in the event handler you change it visible
<TextBlock HorizontalAlignment="Left" Visibility="Collapsed" Name="ErrorBlock" Text="Authentication Failed." VerticalAlignment="Top" Foreground="Red" FontWeight="Bold" />
From the c#
ErrorBlock.Visibility = System.Windows.Visibility.Visible;
The other option is to programmatically create the control and add them to a parent for example the grid see the following link to have a sample of adding rectangle to a grid
http://forums.silverlight.net/t/135977.aspx/1
Upvotes: 0