绑定已加载的事件
本文关键字:事件 加载 绑定 | 更新日期: 2023-09-27 18:12:24
我试图显示一个登录窗口一旦我的主窗口加载,同时坚持MVVM模式。所以我试图将我的主窗口加载事件绑定到我的视图模型中的事件。以下是我尝试过的:
MainWindowView.xaml
<Window x:Class="ScrumManagementClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="ViewModel.MainWindowViewModel"
Loaded="{Binding ShowLogInWindow}">
<Grid>
</Grid>
</Window>
MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ScrumManagementClient.ViewModel
{
class MainWindowViewModel : ViewModelBase
{
public void ShowLogInWindow(object sender, EventArgs e)
{
int i = 0;
}
}
}
我得到的错误信息是"Loaded="{Binding ShowLogInWindow}"是无效的。'{Binding ShowLogInWindow}'不是一个有效的事件处理程序方法名。只有生成的或代码隐藏类上的实例方法才是有效的。"
你将不得不使用System.Windows.Interactivity dll。
然后在XAML中添加名称空间:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
然后你可以这样做:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding MyICommandThatShouldHandleLoaded}" />
</i:EventTrigger>
</i:Interaction.Triggers>
请注意,您将不得不使用ICommand
(或DelegateCommand,如果您使用Prism,或RelayCommand,如果您使用MVVMLight),并且您的窗口的DataContext必须持有iccommand。
使用附加行为。这在MVVM ....是允许的
(下面的代码可能会/可能不会这样编译)
XAML…
<Window x:Class="..."
...
xmlns:local="... namespace of the attached behavior class ..."
local:MyAttachedBehaviors.LoadedCommand="{Binding ShowLogInWindowCommand}">
<Grid>
</Grid>
</Window>
代码后面…
class MainWindowViewModel : ViewModelBase
{
private ICommand _showLogInWindowCommand;
public ICommand ShowLogInWindowCommand
{
get
{
if (_showLogInWindowCommand == null)
{
_showLogInWindowCommand = new DelegateCommand(OnLoaded)
}
return _showLogInWindowCommand;
}
}
private void OnLoaded()
{
//// Put all your code here....
}
}
和附加行为…
public static class MyAttachedBehaviors
{
public static DependencyProperty LoadedCommandProperty
= DependencyProperty.RegisterAttached(
"LoadedCommand",
typeof(ICommand),
typeof(MyAttachedBehaviors),
new PropertyMetadata(null, OnLoadedCommandChanged));
private static void OnLoadedCommandChanged
(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
var frameworkElement = depObj as FrameworkElement;
if (frameworkElement != null && e.NewValue is ICommand)
{
frameworkElement.Loaded
+= (o, args) =>
{
(e.NewValue as ICommand).Execute(null);
};
}
}
public static ICommand GetLoadedCommand(DependencyObject depObj)
{
return (ICommand)depObj.GetValue(LoadedCommandProperty);
}
public static void SetLoadedCommand(
DependencyObject depObj,
ICommand value)
{
depObj.SetValue(LoadedCommandProperty, value);
}
}
DelegateCommand
源代码可以在网上找到…它是最适合MVVM的ICommand API。
更新:
我写了一篇关于方法绑定的一个更灵活的新版本的文章,它在这里使用了稍微不同的语法:
http://www.singulink.com/CodeIndex/post/updated-ultimate-wpf-event-method-binding完整的代码清单在这里:
https://gist.github.com/mikernet/7eb18408ffbcc149f1d9b89d9483fc19任何未来的更新都会发布到博客上,所以我建议在那里查看最新版本。
原始答:
。. NET 4.5+现在支持事件的标记扩展。我用它来创建一个方法绑定,可以这样使用:
<!-- Basic usage -->
<Button Click="{data:MethodBinding OpenFromFile}" Content="Open" />
<!-- Pass in a binding as a method argument -->
<Button Click="{data:MethodBinding Save, {Binding CurrentItem}}" Content="Save" />
<!-- Another example of a binding, but this time to a property on another element -->
<ComboBox x:Name="ExistingItems" ItemsSource="{Binding ExistingItems}" />
<Button Click="{data:MethodBinding Edit, {Binding SelectedItem, ElementName=ExistingItems}}" />
<!-- Pass in a hard-coded method argument, XAML string automatically converted to the proper type -->
<ToggleButton Checked="{data:MethodBinding SetWebServiceState, True}"
Content="Web Service"
Unchecked="{data:MethodBinding SetWebServiceState, False}" />
<!-- Pass in sender, and match method signature automatically -->
<Canvas PreviewMouseDown="{data:MethodBinding SetCurrentElement, {data:EventSender}, ThrowOnMethodMissing=False}">
<controls:DesignerElementTypeA />
<controls:DesignerElementTypeB />
<controls:DesignerElementTypeC />
</Canvas>
<!-- Pass in EventArgs -->
<Canvas MouseDown="{data:MethodBinding StartDrawing, {data:EventArgs}}"
MouseMove="{data:MethodBinding AddDrawingPoint, {data:EventArgs}}"
MouseUp="{data:MethodBinding EndDrawing, {data:EventArgs}}" />
<!-- Support binding to methods further in a property path -->
<Button Content="SaveDocument" Click="{data:MethodBinding CurrentDocument.DocumentService.Save, {Binding CurrentDocument}}" />
查看模型方法签名:
public void OpenFromFile();
public void Save(DocumentModel model);
public void Edit(DocumentModel model);
public void SetWebServiceState(bool state);
public void SetCurrentElement(DesignerElementTypeA element);
public void SetCurrentElement(DesignerElementTypeB element);
public void SetCurrentElement(DesignerElementTypeC element);
public void StartDrawing(MouseEventArgs e);
public void AddDrawingPoint(MouseEventArgs e);
public void EndDrawing(MouseEventArgs e);
public class Document
{
// Fetches the document service for handling this document
public DocumentService DocumentService { get; }
}
public class DocumentService
{
public void Save(Document document);
}
更多细节可在这里找到:http://www.singulink.com/CodeIndex/post/building-the-ultimate-wpf-event-method-binding-extension
完整的类代码在这里:https://gist.github.com/mikernet/4336eaa8ad71cb0f2e35d65ac8e8e161
在AttachedCommandBehavior V2中提出了一种更通用的使用行为的方法,即ACB,它甚至支持多个事件到命令绑定,
下面是一个非常基本的用法示例:
<Window x:Class="Example.YourWindow"
xmlns:local="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
local:CommandBehavior.Event="Loaded"
local:CommandBehavior.Command="{Binding DoSomethingWhenWindowIsLoaded}"
local:CommandBehavior.CommandParameter="Some information"
/>
对于VS 2013 Update 5,我无法绕过"无法转换类型为'System.Reflection '的对象"。RuntimeEventInfo'类型为'System.Reflection.MethodInfo '。在"Core"目录下,我做了一个简单的接口
interface ILoad
{
void load();
}
我的viewModel已经有load()函数实现了ilload。在我的. example .cs中,我通过ilload调用ViewModel load()。
private void ml_Loaded(object sender, RoutedEventArgs e)
{
(this.ml.DataContext as Core.ILoad).load();
}
除了POCO加载之外,xaml.cs对ViewModel一无所知,而ViewModel对xaml.cs一无所知。ml_loaded事件被映射到ViewModel load()。