绑定滑块控件的事件

1 wpf xaml binding mvvm

在视图(AudioView.xaml)中,我编写了以下代码

<Slider
    Name="AudioSlider"
    Width="200"
    Height="23"
    Grid.Column="0"
    IsSelectionRangeEnabled="True"
    IsSnapToTickEnabled="True"
    Maximum="{Binding Path=TotalAudioPlayingSeconds, Mode=OneTime}"
    Minimum="0"
    Style="{StaticResource CustomStyleForSlider}"
    Thumb.DragCompleted="{Binding AudioSliderChangedCommand}"
    TickFrequency="1"
    Value="{Binding Path=AudioPosition}"/>
Run Code Online (Sandbox Code Playgroud)

注意:还有文件AudioView.xaml.cs.

在视图模型class(AudioViewModel.cs)中,我定义了以下属性

public event DragCompletedEventHandler AudioSliderChangedCommand;
Run Code Online (Sandbox Code Playgroud)

并在视图模型类(AudioViewModel.cs)的构造函数中

this.AudioSliderChangedCommand = new DragCompletedEventHandler(OnAudioSliderChanged);
Run Code Online (Sandbox Code Playgroud)

在编译期间,我收到以下错误

错误8 DragCompleted ="{Binding AudioSliderChangedCommand}"无效.{Binding AudioSliderChangedCommand}不是有效的事件处理程序方法名称.只有生成的或代码隐藏类上的实例方法才有效.

Jon*_*Jon 6

问题不在你的代码隐藏中,而是在你的XAML中.在某处你这样做:

DragCompleted="{Binding AudioSliderChangedCommand}"
Run Code Online (Sandbox Code Playgroud)

这指示XAML反序列化AudioSliderChangedCommand程序将处理程序附加到DragCompleted事件.但是,AudioSliderChangedCommand不是与适当的签名(其可作为处理程序附后),这是一个方法不是在您的视图类.最后,您不能Binding用于事件处理程序.

要解决这个问题,最简单的解决方案是在您的View:

private void DragCompletedEventHandler(object sender, DragCompletedEventArgs e)
{
    var viewModel = (YourViewModelType)this.DataContext;
    viewModel.OnAudioSliderChanged(this, e);
}
Run Code Online (Sandbox Code Playgroud)

并且也改变了

DragCompleted="{Binding AudioSliderChangedCommand}"
Run Code Online (Sandbox Code Playgroud)

DragCompleted="DragCompletedEventHandler"
Run Code Online (Sandbox Code Playgroud)

在你的XAML中.

以上是如何工作的:

  1. 在View中,何时DragCompleted引发,View.DragCompletedEventHandler将调用该方法
  2. 此方法将从AudioSliderChangedCommandViewModel 获取事件(请参阅下面的注释)并将其提升,并传递原始事件args

重要的提示

您似乎对事件,事件处理程序和命令感到困惑.您现有的代码具有误导性.AudioSliderChangedCommand是一个event,但顾名思义它是一个ICommand.适当的名称是AudioSliderChanged.

另外,适当的MVVM方式是通过使用一些风格DelegateCommand(所有体面的MVVM框架都有一个;我在Prism中使用类名进行实现).然后,假设这AudioSliderChangedCommand确实是一个命令,View中的代码隐藏将是:

private void DragCompletedEventHandler(object sender, DragCompletedEventArgs e)
{
    var viewModel = (YourViewModelType)this.DataContext;
    viewModel.AudioSliderChangedCommand.Execute();
}
Run Code Online (Sandbox Code Playgroud)

通过使用一些"事件来命令"附加行为,也可以完全没有任何代码隐藏.