我是WPF的新手,我正在寻找一些指导。
我正在开发一个应用程序,用于打印我们的履行部门的工单。
现在我有2个窗口:第一个是主屏幕,第二个是带有gridview的窗口,用于保存要打印的工单。
第一页上会有几个按钮。每个按钮都会打开第二个窗口;但是,根据单击的按钮,传递到将加载数据的服务的参数将不同。
这样做的最佳做法是什么?
修改
举一个粗略的例子(这是非常简单的),说我有两套标准:OrderTypes:{Rush,Today,Future}和Locations {Warehouse 1,Warehouse 2,Warehouse 3}
主窗口将有一个3x3网格按钮,每个组合一个。我希望能够在一个按钮“Expedite& Warehouse 1”上指定;然后将这些参数传递回单个方法,这将打开第二个窗口。
答案 0 :(得分:3)
假设您有MainWindow
并且按钮已放入其中。
为MainWindow创建MainWindowViewModel
并将其设置为DataContext
。
在ViewModel和绑定按钮Command上使用此ICommand
进行ICommand
,以便打开另一个窗口的入口点为单个。对于ICommand,您可以使用RelayCommand
或DelegateCommand
,无论哪个最适合您。
现在,您需要打开窗口并根据按钮类型单击将参数传递给它。我建议让Enum描述需要根据不同按钮执行的动作。
<强>枚举强>
public enum ActionType
{
Action1,
Action2,
Action3 and so on...
}
并从这样的按钮绑定:
<Button Command="{Binding CommandInstance}"
CommandParameter="{x:Type local:ActionType.Action1}"/>
<Button Command="{Binding CommandInstance}"
CommandParameter="{x:Type local:ActionType.Action2}"/>
其中local将是枚举枚举的命名空间。
在命令中,execute delegate将枚举值传递给另一个窗口构造函数:
private void CommandMethod(ActionType action)
{
AnotherWindow anotherWindow = new AnotherWindow(action);
anotherWindow.Show();
}
从构造函数中传递的动作中,您可以检查需要传递给负责加载数据的服务的参数。
此外,如果从ViewModel创建窗口似乎不正确,您可以在窗口控件上安装Service包装器,它负责显示/关闭窗口。
<强>更新强>
由于您希望从Views传递多个参数,因此为此维护枚举将非常麻烦。您可以使用IMultiValueConverter 从View中传递多个值。
让我用一个小例子来解释:
<Button Command="{Binding TestCommand}">
<Button.Resources>
<sys:String x:Key="Rush">Rush</sys:String>
<sys:String x:Key="Warehouse">Warehouse</sys:String>
</Button.Resources>
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource MultiValuesReturnConverter}">
<Binding Source="{StaticResource Rush}"/>
<Binding Source="{StaticResource Warehouse}"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
其中sys
将是XAML中System的名称空间:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
所以,现在你可以在XAML中自由地将许多对象从XAML传递给你的命令参数。您所要做的就是在Button资源部分下声明资源,并将其作为绑定传递给转换器。
转换器代码 将其转换为可作为单个参数对象传递给命令的参数列表:
public class MultiValuesReturnConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType,
object parameter, CultureInfo culture)
{
return values.ToList<object>();
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
命令方法:
private void CommandMethod(object parameter)
{
// Now you have all the parameters here to take decision.
IList<object> values = parameter as List<object>;
AnotherWindow anotherWindow = new AnotherWindow(action);
anotherWindow.Show();
}
答案 1 :(得分:1)
如果您不想使用某些第三方库,只需将参数通过click事件传递到其他窗口的构造函数中就没有问题。如果您的数据由viewmodel表示,您也可以传递该viewmodel而不是参数本身。
MVVM的一点不是“没有代码隐藏”。很多时候你最终会没有代码隐藏,但尝试以这种方式开发应用程序会导致你进入复杂的反模式,通常比简单的点击事件和“旧方式”更多的工作和更多的代码行。
将您的数据视为数据,尝试在可测试的视图模型中完成所有工作,并且永远不要过于严格地遵循模式,以免最终出现大量不可读的抽象。
答案 2 :(得分:0)
在详细说明任何事情之前,我会建议你使用第三方库MVVMLight,它有许多有用的功能,如Messenger,它自己的RelayCommands等......
Tag:获取或设置可用于存储有关此元素的自定义信息的任意对象值。 (继承自FrameworkElement。)
CommandParameter:
<Button Content="Parameterized Command"
Command="{Binding ParameterizedCommand}" CommandParameter={Binding SomeObject} />
希望我涵盖了您可能需要的最重要的部分。
答案 3 :(得分:0)
最简单直观的方法(使用INotifyPropertyChanged
更新用户界面而不是DependencyProperty
):
您在[{1}}
中为DataContext
创建一个属OrderViewModel
的媒体资源
MainWindowViewModel
现在,无论您创建订单视图的方式如何:
class MainWindowViewModel : ViewModelBase // ViewModelBase should implement INotifyPropertychanged, unless you're using dependency properties
{
private OrderViewModel _OrderViewModelInstance;
public OrderViewModel OrderViewModelInstance
{
get{ return _OrderViewModel;}
set { _OrderViewModel = value;
OnPropertyChanged("OrderViewModel")} // Method from ViewModelBase
}
(假设点击按钮时)中实例化OrderViewModel
。MainWindowViewModel
绑定到XAML中的DataContext
。您可能想要创建一个额外的变量,告诉您窗口何时可见。