WPF事件绑定到ViewModel(对于非Command类)

Rob*_*erd 19 c# xaml binding mvvm viewmodel

我正在使用应用程序的第二个版本,作为重写的一部分,我必须转向MVVM架构.我正面临压力,要在视图模型类中放置绝对的所有代码 - 在代码隐藏文件中使用c#是不受欢迎的.(我知道,我知道......我知道背后的代码不是坏事,但这次不是我的电话).

对于实现命令界面的对象,这很容易.我已经能够找到大量关于如何将这些对象的Command绑定到视图模型中的ICommand的信息.问题是没有这种接口的对象,例如

<ListBox
   x:Name="myListBox"
   MouseDoubleClick="myCallbackFunction">

<!-- ... -->

</ListBox>
Run Code Online (Sandbox Code Playgroud)

我想知道如何将Listbox的MouseDoubleClick事件绑定到myCallbackFunction,这是在视图模型中实现的.这甚至可能吗?

谢谢!

Ree*_*sey 8

这不是直接可能的.它可以通过附加属性或行为来完成,但找到并调用适当的方法仍然有点棘手(这可以通过Reflection很容易地完成).

话虽如此,这通常是通过以下方式处理的ICommand:例如,MVVM Light具有很好的EventToCommand行为,可以将任何事件映射到ViewModel上的ICommand.使用ICommand的优点是您仍然可以使用DataBinding,因为ICommand是作为属性公开的.


Mik*_*ski 5

WPF从.NET 4.5开始支持事件的标记扩展。使用该功能,我实现了一个非常多才多艺的方法绑定扩展,并在此处进行了描述:

http://www.singulink.com/CodeIndex/post/building-the-ultimate-wpf-event-method-binding-extension

可用于使用完整属性路径语法绑定到方法,支持绑定和其他标记扩展作为参数,并自动路由到与所提供参数签名匹配的方法。以下是一些用法示例:

<!--  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}}" />
Run Code Online (Sandbox Code Playgroud)

查看模型方法签名:

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);
}
Run Code Online (Sandbox Code Playgroud)