MVVM的几乎所有示例都是具有视图的应用程序,该视图可以由列表框、文本框、标签、按钮等组成。来呈现和处理数据。ListBox、TextBox和Label绑定到ViewModel中的属性,而Buttons绑定到Commands。这些类型的视图本质上主要是静态的。
然而,没有任何真实的例子来说明如何处理流体视图,例如绘图程序。当你想到它的时候,绘图程序只是一个画布。因为既没有要绑定的按钮,也没有要交互的列表框、文本框或标签,那么您应该如何与Canvas交互?
到目前为止,我发现与Canvas交互的唯一方法是使用Canvas的代码隐藏来使用鼠标事件,以允许您通过公开的方法将数据传递到ViewModel中,如Add(Point point point),该方法将添加一个点到ObservableCollection中,仅绑定到ItemsControl,后者将基于ItemTemplate处理点数据。
CanvasView
<ItemsControl x:Name="itemsControl" ItemsSource="{Binding CanvasObjectModels}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="1000" Height="1000" Background="GhostWhite"
MouseDown="Canvas_MouseDown"/>-->
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Origin.X}" />
<Setter Property="Canvas.Top" Value="{Binding Origin.Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<CanvasObject:Node Origin="{Binding Origin}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
IMyCanvas
public interface IMyCanvas
{
public void AddCanvasObject(Point origin);
}
CanvasView Code-Behind
public partial class CanvasView : UserControl
{
private IMyCanvas pViewModel;
public CanvasView()
{
InitializeComponent();
Loaded += InitializeViewModel;
}
private void InitializeViewModel(object sender, RoutedEventArgs e)
{
if (DataContext is IMyCanvas viewModel)
pViewModel = viewModel;
else
throw new Exception("DataContext does not implement IMyCanvas!");
Loaded -= InitializeViewModel;
}
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
var canvas = sender as Canvas;
if (e.LeftButton == MouseButtonState.Pressed)
{
pViewModel.AddCanvasObject(e.GetPosition(canvas));
}
}
}
画布对象模型
public class CanvasObjectModel
{
public Point Origin { get; set; }
}
画布视图模型
internal class CanvasViewModel : ViewModelBase, IMyCanvas
{
public ObservableCollection<CanvasObjectModel> CanvasObjectModels { get; set; }
public CanvasViewModel()
{
CanvasObjectModels = new ObservableCollection<CanvasObjectModel>();
}
public void AddCanvasObject(Point origin)
{
CanvasObjectModels.Add(new CanvasObjectModel() { Origin = origin});
}
}
有没有更好的方法来做到这一点?
2条答案
按热度按时间h7appiyu1#
如果要将事件绑定到VM命令,可以使用Interactivity:
有关更多信息,请查看the question
ogsagwnx2#
您可以使用
Microsoft.Xaml.Behaviors.Wpf
(NuGet Package)中的CallMethodAction
行为,直接从XAML调用视图模型方法。我给你一个按钮的例子,但是你可以用同样的方式处理画布上的事件
1.将此命名空间添加到您的XAML中:
2.将 CallMethodAction 触发器添加到XAML中的按钮中:
3.在视图模型中放入IncrementCount方法:
现在您可以跳过后面代码中的样板代码。此外,您可以在这里查看XamlBehaviorsWpf wiki:https://github.com/Microsoft/XamlBehaviorsWpf/wiki还有其他一些行为:)