【发布时间】:2020-12-10 08:33:20
【问题描述】:
在我的 C# WPF MVVM 模式应用程序中,我的视图中有一个 ItemsControl,它基于在 XAML 中定义的绑定 ItemsSource 在画布上绘制线条和按钮:
<Window.DataContext>
<viewmodels:MainWindowViewModel />
</Window.DataContext>
.
.
.
<ItemsControl
x:Name="DiagramViewCanvas"
ItemsSource="{Binding DiagramObjects, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:LineObject}">
<Line
X1="{Binding XStart}"
Y1="{Binding YStart}"
X2="{Binding XEnd}"
Y2="{Binding YEnd}"
Stroke="White"
StrokeThickness="1"
SnapsToDevicePixels="True"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ButtonObject}">
<Button
Style="{DynamicResource MyDiagramButtonStyle}"
Width="225"
Height="30"
Content="{Binding Content}"
FontSize="13"
SnapsToDevicePixels="True">
</Button>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="Black" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding XPosition, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="Canvas.Top" Value="{Binding YPosition, UpdateSourceTrigger=PropertyChanged}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
这段代码运行良好。我的问题是如何将按钮的 Click 事件绑定到 ViewModel (MainWindowViewModel) 中的方法。
选项 1(由于 MVVM 模式,我不想使用它):如果我尝试如下简单的 Click 事件定义...
<Button
Style="{DynamicResource MyDiagramButtonStyle}"
Width="225"
Height="30"
Content="{Binding Content}"
FontSize="13"
SnapsToDevicePixels="True"
Click="OnButtonClick"/>
...其中 OnButtonClick 在我的 XAML 代码隐藏中定义,OnButtonClick 方法被成功调用并为在运行时创建的每个 Button 执行。它工作正常。
选项 2: 但是,如果我尝试使用 Interaction.Triggers 如下(这是我经常使用的方法,在我的代码中没有任何问题)以避免将代码放在后面的代码中......
<Button
Style="{DynamicResource MyDiagramButtonStyle}"
Width="225"
Height="30"
Content="{Binding Content}"
FontSize="13"
SnapsToDevicePixels="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:CallMethodAction TargetObject="{Binding}" MethodName="OnButtonClick"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
...在我的 MainWindowViewModel 中定义 OnButtonClick ...
public void OnButtonClick(object sender, RoutedEventArgs e)
{
if (sender is Button btn)
{
// do something
}
}
... 我收到以下错误:
System.ArgumentException: 'Could not find method named 'OnButtonClick' on object of type 'ButtonObject' that matches the expected signature.'
问题 1: 我在实现交互触发器时是否犯了一个基本错误(我的代码中有许多其他交互触发器完全可以正常工作)?还是在运行时动态创建 Button 的情况下 Interaction.Triggers 不起作用?
问题 2:我是否应该改用 ICommand(例如 Binding Commands to Events? 中提到的)?
感谢您对我做错的任何指导。
【问题讨论】:
-
“我希望 OnButtonClick 方法驻留在我的 ViewModel 中”,因此您基本上想丢弃 mvvm 的所有原则。 wpf 每一步都会为你加油,祝你好运
-
忘记点击事件处理程序和触发器。只需在您的
ButtonObject类中包含一个ICommand项目并直接绑定到该项目。