Balinator
Balinator

Reputation: 106

WPF MVVM Canvas ClickEvent

i'm creating an application in WPF using MVVM and i'm in a dificult situation becouse i can not bind a command to a Canvases ClickEvent.

I want to put some rectangels on the Canvas and save thair position to a database, but if i placed to the wrong place and i click on it it would move along the cursor until the next click.

XAML file:

<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>

The part from the MainVindowViewModel that is actualy used in this part:

    #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

Upvotes: 2

Views: 1615

Answers (1)

Balinator
Balinator

Reputation: 106

Ok, i solved the problem, just needed some libs and a litle work on the code. With the NuGetManager i installed the Unofficial.Blend.Interactivity (in the xaml file the 'i') package and the MvvmLightLibs (in the xaml file the 'mvvm') package.

The in xaml file I added this lines:

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>

And in the 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));
}

Upvotes: 2

Related Questions