[英]How do I bind an event captured by a XAML element to a method in an arbitrary class in C#?
我是 C# 新手,正在尝试构建一个简单的 MVVM 应用程序,但我无法将 XAML 视图中的事件绑定到 Model 或 ViewModel 中的方法。 我理解为什么使用 MVVM,并且感觉我对如何将 MVVM 应用程序放在一起有了大致的了解,但我迷失在细节中。 如果看起来我不知道自己在做什么,我会提前道歉,但我不知道,尽管阅读了很多关于这个主题的文章。
我希望在单击按钮时执行 MainScreenViewModel 中的 btnUpdate_Click,但出现错误
MC6005 Click="vm:btnUpdate_Click" 无效。 “vm:btnUpdate_Click”不是有效的事件处理程序方法名称。 只有生成或代码隐藏 class 上的实例方法才有效。
如果我的类是公共的并且在同一个命名空间中,我需要做什么才能使它们在我的视图中可见? 我不想将方法移回 MainWindow class。
<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();
}
}
公开 ICommand 的示例 ViewModel(不是您示例中的常规方法)。 单击按钮后它将更改 Text 属性的值 - 只是为了表明它有效。
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();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.