如何将XAML元素捕获的事件绑定到c#中任意类中的方法?



我是一个c#新手试图建立一个简单的MVVM应用程序,我有麻烦在我的XAML视图的事件在我的模型或ViewModel的方法。我理解为什么使用MVVM,感觉我得到了如何将MVVM应用程序放在一起的大致笔触,但我迷失在细节中。如果我看起来不知道自己在做什么,我先道歉,但我确实不知道,尽管我在这个主题上读了很多书。

我希望btnUpdate_Click在MainScreenViewModel执行时,按钮被点击,但我得到错误

MC6005点击="vm: btnUpdate_Click"无效。'vm:btnUpdate_Click'不是一个有效的事件处理程序方法名。只有生成的或代码隐藏类上的实例方法才是有效的。

如果我的类是公共的,并且在同一个命名空间中,我需要做些什么才能使它们从我的视图中可见?我不想把方法移回MainWindow类。

<Window x:Class="SFM_Calculator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SFM_Calculator"
xmlns:vm="MainScreenViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
>
<Window.DataContext>
<local:SFMModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
...
<ColumnDefinition/>
</Grid.ColumnDefinitions>
...
</Grid.RowDefinitions>
...
<Button
Grid.Column="1"
Grid.Row="2"
x:Name="btnUpdate"
Content="Update"
Click="vm:btnUpdate_Click"
/>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Linq;
using System.ComponentModel;
namespace SFM_Calculator
{
public class MainScreenViewModel : INotifyPropertyChanged
{
private void btnUpdate_Click(object sender, System.Windows.RoutedEventArgs e)
{
TestInt = 999;
}

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}

public SFMModel sfmModel = new SFMModel();
private int _testInt;
public int TestInt
{
get { return _testInt; }
set { _testInt = value; }
}
public MainScreenViewModel()
{                        
Debug.WriteLine("Got here.");
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace SFM_Calculator
{
public class SFMModel : INotifyPropertyChanged
{
private int _tprop;
public int TProp
{
get { return _tprop; }
set { _tprop = value; }
}
public SFMModel ()
{
TProp = 69;
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Configuration;
namespace SFM_Calculator
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

您的viewModel应该公开命令,而不是方法。另外,您应该通过绑定机制访问暴露的命令。

实现所需ICommand接口的示例命令

internal class Command : ICommand
{
private readonly Action execute;
public Command(Action execute)
{
this.execute = execute;
}
public event EventHandler? CanExecuteChanged;
public bool CanExecute(object? parameter)
{
return true;
}
public void Execute(object? parameter)
{
execute();
}
}

显示iccommand的示例ViewModel(不是您示例中的常规方法)。它会在点击按钮后改变文本属性的值-只是为了显示它的工作。

internal class ViewModel : INotifyPropertyChanged
{
public string Text { get; private set; }
public ICommand AwesomeCommand { get; }
public ViewModel()
{
AwesomeCommand = new Command(() => { 
Text = "Button clicked"; 
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text))); 
});
}
public event PropertyChangedEventHandler? PropertyChanged;
}

主窗口:

<StackPanel>
<Button Command="{Binding AwesomeCommand}"></Button>
<Label Content="{Binding Text}" Height="100"></Label>
</StackPanel>

MainWindow后面的代码,连接ViewModel和视图(MainWindow):

public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}

最新更新