如何从silverlight中的用户控件的视图模型类中打开另一个用户控件?

时间:2012-04-13 11:53:14

标签: silverlight mvvm

我是MVVM模型的新手。我有一个用户控件,有多个按钮。我正在通过RoutedEvent处理视图模型类中这些按钮的click事件。我必须在按钮的单击事件中调用/打开另一个用户控件。怎么做到这一点?

提前致谢...

3 个答案:

答案 0 :(得分:3)

你所描述的是大多数MVVM新手挣扎的问题之一 - 导航。我试图避免让我的任何一个Viewmodel都不知道它自己的视图(视图模型应该是非常不可见的视图)或任何其他视图。

解决此问题的一种方法是在应用程序中使用一个处理所有导航的中央组件。我们称之为NavigationController。该组件处理导航请求,负责创建视图(以及可选的关联视图模型)及其初始化,它是应用程序中唯一真正了解各种ViewModel及其各自视图之间相互依赖关系的组件。

理想情况下,ViewModel和Controller之间的通信是通过事件聚合器(例如TinyMessenger)执行的,这样可以轻松实现松散耦合的导航(以及更多)。

作为最后的评论,我怀疑你是想要提出一个简单的UserControl,而是某种对话框,这意味着在子窗口中托管UserControl。这可以通过我已经概述的方法来解决。

答案 1 :(得分:0)

您可以将控件放在XAML中,并将visibility属性设置为折叠,并在事件处理程序中将其更改为可见

<TextBlock HorizontalAlignment="Left" Visibility="Collapsed" Name="ErrorBlock" Text="Authentication Failed." VerticalAlignment="Top" Foreground="Red" FontWeight="Bold" />

来自c#

ErrorBlock.Visibility = System.Windows.Visibility.Visible;

另一个选项是以编程方式创建控件并将它们添加到父级,例如网格,请参阅以下链接以获取向网格添加矩形的示例

http://forums.silverlight.net/t/135977.aspx/1

答案 2 :(得分:0)

要做你想做的事,你需要使用控件和表单的组合。请注意,我的回答适用于Silverlight 4及更高版本。 首先,我将按钮“COMMAND”绑定到视图模型命令实现。在以下示例中,我的控件的DataContext是我的视图模型的一个实例。我的ViewModel实现了一组Keys(字符串)和ViewModelCommand类的哈希表。忽略实现的复杂性。重点是Button被限制为“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}"
                    >

在上面的示例中,命令绑定到在“FIND”下索引的命令。它与直接绑定到命令相同。下一个重要的部分是CommandParameter。这是您希望在新窗口中显示的控件的隐藏实例。在这种情况下,控件的名称是'enHiddenControl'。您可以将此控件放在屏幕上的任何位置,只需确保其隐藏即可。这将作为命令的方法签名中的参数。例如:

    /// <summary>
    /// Finding an existing customer
    /// </summary>
    /// <param name="sender">The command parameter - control </param>
    /// <param name="e"></param>
    public void OnChangeCustomer(object sender)...

当这个发件人进来时,目标是获取类型并使用激活器来创建该类的实例。 Activator位于 System.Reflection System.Reflection.Emit 中。 (我从头顶打字,这主要是理论上的,但应该有效;)

Activator.CreateInstance(sender.GetType())

创建此类的实例后,将其添加到“ChildControl”上的LayoutGrid中。怎么样?创建一个网格,将其命名为“LayoutRoot”。创建ChildControl,将网格添加到子控件,然后将刚刚创建的实例添加到网格中。显示表格。从理论上讲,您只需动态创建一个包含控件的表单,而无需了解特定的类。只有仿制药。形式的大小......这是另一个故事。我会在宽度和高度上使用Auto。因此,控制的大小应该从理论上决定表格的大小。

最后,该方法应如下所示:

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();
        }
}

所有这些都是理论上的,并且从未经过测试,但它应该有效,因为我已经在C#中引入了这些性质的特技。