我是 MVVM 模型的新手。我有一个带有按钮数量的用户控件。我正在通过 RoutedEvent 处理视图模型类中这些按钮的单击事件。我必须在按钮的单击事件中调用/打开另一个用户控件。如何做到这一点?
提前致谢...
我是 MVVM 模型的新手。我有一个带有按钮数量的用户控件。我正在通过 RoutedEvent 处理视图模型类中这些按钮的单击事件。我必须在按钮的单击事件中调用/打开另一个用户控件。如何做到这一点?
提前致谢...
您所描述的是大多数 MVVM 新手都在努力解决的问题之一 - 导航。一般来说,我试图避免让我的任何 Viewmodel 对它自己的视图(视图模型应该是漂亮的视图不可知论)或任何其他视图都没有任何知识。
解决此问题的一种方法是在您的应用程序中使用一个中央组件来处理所有导航。我们称它为 NavigationController。该组件处理导航请求并负责创建视图(以及可选的关联视图模型)及其初始化,它是应用程序中唯一真正了解各种视图模型及其各自视图之间的相互依赖关系的组件。
理想情况下,ViewModel 和控制器之间的通信是通过事件聚合器(例如TinyMessenger)执行的,这使得实现松散耦合的导航(以及更多)变得容易。
最后,我怀疑您的意思是要调出一个简单的 UserControl,而是要调出某种对话框,这意味着 UserControl 托管在子窗口中。这也可以使用我概述的方法来解决。
要执行您想做的事情,您需要结合使用控件和表单。请注意,我的回答适用于 Silverlight 4 及更高版本。首先,我会将按钮“COMMAND”绑定到视图模型命令实现。在以下示例中,我的控件的 DataContext 是我的视图模型的一个实例。我的 ViewModel 实现了一组 Keys(strings) 和 ViewModelCommand 类的哈希表。忽略实现的复杂性。关键是按钮绑定到“命令”
<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)...
当这个发送者进来时,目标是获取类型并使用激活器创建该类的实例。激活器位于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# 中完成此类特技的次数,它应该可以工作。
要么将控件放在 XAML 中,并将可见性属性设置为折叠,然后在事件处理程序中将其更改为可见
<TextBlock HorizontalAlignment="Left" Visibility="Collapsed" Name="ErrorBlock" Text="Authentication Failed." VerticalAlignment="Top" Foreground="Red" FontWeight="Bold" />
从 C#
ErrorBlock.Visibility = System.Windows.Visibility.Visible;
另一个选项是以编程方式创建控件并将它们添加到父级,例如网格请参阅以下链接以获取将矩形添加到网格的示例