C# WPF MVVM画布单击事件

C# WPF MVVM画布单击事件,c#,wpf,xaml,mvvm,data-binding,C#,Wpf,Xaml,Mvvm,Data Binding,我正在使用MVVM在WPF中创建一个应用程序,我遇到了一个困难的情况,因为我无法将命令绑定到Canvases ClickEvent 我想在画布上放置一些矩形并将其位置保存到数据库中,但是如果我放置到错误的位置并单击它,它将沿着光标移动,直到下一次单击为止 XAML文件: <UserControl x:Class="View.TheaterManageRoom" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/pres

我正在使用MVVM在WPF中创建一个应用程序,我遇到了一个困难的情况,因为我无法将命令绑定到Canvases ClickEvent

我想在画布上放置一些矩形并将其位置保存到数据库中,但是如果我放置到错误的位置并单击它,它将沿着光标移动,直到下一次单击为止

XAML文件:

<UserControl x:Class="View.TheaterManageRoom"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:View"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="10*"/>
    </Grid.RowDefinitions>
    <StackPanel Margin="5"
                Orientation="Horizontal">
        <Label Content="RoomName:"/>
        <TextBox VerticalContentAlignment="Center"
                 HorizontalContentAlignment="Center" 
                 Width="100"/>
    </StackPanel>
    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>
        <StackPanel Orientation="Vertical">
            <Label Margin="5"
                   Content="Seat multiplier:"/>
            <TextBox Margin="5" Text="{Binding TheaterManageRoomMultiplier, UpdateSourceTrigger=PropertyChanged}"/>
            <Button Margin="5">Add Seat</Button>
            <Button Margin="5">Stage</Button>
            <Button Margin="5">Save</Button>
        </StackPanel>
        <ItemsControl ItemsSource="{Binding TheaterManageRoomPoints}" 
                      Margin="10"
                      Grid.Column="1">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas IsItemsHost="True"
                            Background="White"
                            MouseUp="{Binding TheaterManageRoomMouseClick}">

                    </Canvas>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Canvas.Left" Value="{Binding X}"/>
                    <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="{Binding BorderColor}" Background="{Binding FillColor}" BorderThickness="1" Width="{Binding Width}" Height="{Binding Height}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <!--<Canvas Name="TheaterManageRoomCanvas" 
                Margin="10"
                Background="White"
                Grid.Column="1"></Canvas>-->
    </Grid>
</Grid>

增加座位
阶段
拯救

此零件中实际使用的MainVindowViewModel中的零件:

    #region TheaterManageRoom
    private Visibility theaterManageRoomVisibility = Visibility.Hidden;

    public Visibility TheaterManageRoomVisibility
    {
        get { return theaterManageRoomVisibility; }
        set
        {
            theaterManageRoomVisibility = value;
            RaisePropertyChanged("TheaterManageRoomVisibility");
        }
    }
    private string theaterManageRoomMultiplier = "";

    public string TheaterManageRoomMultiplier
    {
        get { return theaterManageRoomMultiplier; }
        set
        {
            Regex r = new Regex(@"(^[0-9]+(\.[0-9]*)*$)|(^$)");
            if (r.Match(value).Success)
            {
                theaterManageRoomMultiplier = value;
            }
            RaisePropertyChanged("TheaterManageRoomMultiplier");
        }
    }

    public class RectItem
    {
        public RectItem(double X, double Y, double Width, double Height) {
            this.X = X;
            this.Y = Y;
            this.Width = Width;
            this.Height = Height;
            BorderColor = new SolidColorBrush(Colors.Black);
            FillColor = new SolidColorBrush(Colors.Wheat);
        }
        public SolidColorBrush BorderColor { get; set; }
        public SolidColorBrush FillColor { get; set; }
        public double X { get; set; }
        public double Y { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }
    }
    private ObservableCollection<RectItem> theaterManageRoomPoints;
    public ObservableCollection<RectItem> TheaterManageRoomPoints {
        get { return theaterManageRoomPoints; }
        set {
            theaterManageRoomPoints = value;
            RaisePropertyChanged("TheaterManageRoomPoints");
        }
    }
    public void TheaterManageRoomLoadElements()
    {
        TheaterManageRoomPoints = new ObservableCollection<RectItem>();
        TheaterManageRoomPoints.Add(new RectItem(10,10,5,5));
    }
    public ICommand TheaterManageRoomMouseClick
    {
        get { return new RelayCommand(TheaterManageRoomMouseClickFunc); }
    }
    private void TheaterManageRoomMouseClickFunc() {
        TheaterManageRoomPoints.Add(new RectItem(10, 10, 5, 5));
    }
    #endregion
#将区域划分为终端管理室
私有可见性theaterManageRoomVisibility=可见性.Hidden;
公共能见度术语管理器房间能见度
{
获取{返回TermManagerRoomVisibility;}
设置
{
TheTermManagerRoomVisibility=值;
RaisePropertyChanged(“TheTerm Manager Room可见性”);
}
}
私有字符串theaterManageRoomMultiplier=“”;
公共字符串TheaterManagerRoom乘数
{
获取{返回TheaterManagerRoom乘数;}
设置
{
正则表达式r=新正则表达式(@“(^[0-9]+(\[0-9]*)*$)|(^$)”;
if(r.Match(value).Success)
{
TheTermManagerRoom乘数=数值;
}
RaisePropertyChanged(术语管理室乘数);
}
}
公共类项目
{
公共项目(双X、双Y、双宽、双高){
这个.X=X;
这个。Y=Y;
这个。宽度=宽度;
这个。高度=高度;
BorderColor=新的SolidColorBrush(颜色为黑色);
FillColor=新的SolidColorBrush(Colors.Wheat);
}
公共SolidColorBrush边框颜色{get;set;}
公共SolidColorBrush FillColor{get;set;}
公共双X{get;set;}
公共双Y{get;set;}
公共双宽度{get;set;}
公共双倍高度{get;set;}
}
私人可观测采集终端管理室点;
公共可观测采集终端管理室点{
获取{返回TermManagerRoomPoints;}
设置{
TheTermManagerRoomPoints=值;
RaisePropertyChanged(“TheaterManagerRoomPoints”);
}
}
public void TheaterManageRoomLoadElements()
{
TheTermManagerRoomPoints=新的ObservableCollection();
添加(新项(10,10,5,5));
}
公用图标命令和Term Manager Room鼠标单击
{
获取{returnnewrelaycommand(TheaterManageRoomMouseClickFunc);}
}
私有void TheaterManageRoomMouseClickFunc(){
添加(新项(10,10,5,5));
}
#端区

好的,我解决了这个问题,只需要一些lib和少量代码。 使用NuGetManager,我安装了Unofficial.Blend.Interactivity(在xaml文件中为'i')包和MvvmLightLibs(在xaml文件中为'mvvm')包

在xaml文件中,我添加了以下行:

This two lines at the top:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:mvvm="http://www.galasoft.ch/mvvmlight"

And wit this in the actual code:

<Canvas IsItemsHost="True"
        Background="White">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseLeftButtonUp">
            <mvvm:EventToCommand Command="{Binding TheaterManageRoomClickOnCanvas}" PassEventArgsToCommand="True"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Canvas>
顶部有两行:
xmlns:i=“clr命名空间:System.Windows.Interactivity;assembly=System.Windows.Interactivity”
xmlns:mvvm=”http://www.galasoft.ch/mvvmlight"
在实际的代码中:
在MainVindowViewModel中

public ICommand TheaterManageRoomClickOnCanvas
{
    get { return new RelayCommand<EventArgs>(TheaterManageRoomClickOnCanvasFunc); }
}
private void TheaterManageRoomClickOnCanvasFunc(EventArgs args) {
    MouseEventArgs e = (MouseEventArgs)args;
    var position = e.GetPosition(e.Device.Target);
    TheaterManageRoomPoints.Add(new RectItem(position.X, position.Y));
}
public图标命令和Term Manager Room单击Canvas
{
获取{返回新的RelayCommand(TheTermManagerRoomClickOnCanvasFunc);}
}
private void TheTerm Manager Room ClickOnCanvasFunc(事件args args){
MouseEventArgs e=(MouseEventArgs)args;
var位置=e.GetPosition(e.Device.Target);
TheaterManagerRoomPoints.Add(新的矩形项(position.X,position.Y));
}