Search code examples
c#wpfrectanglesmultibinding

WPF: Write rectangle depends on the mouse position using multibinding


How to write a WPF application that draws a rectangle. The size of the rectangle should depend on the mouse position. The mouse pointer is always at one corner of the rectangle. The rectangle is always centered.

It should look something like this:

enter image description here enter image description here

This is My Code:

XAML:

<Window x:Class="MyNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyNamespace"
        mc:Ignorable="d"
        Title="MainWindow" x:Name="window1" Height="450" Width="800" MouseMove="Grid1_MouseMove">

    <Window.Resources>
        <local:SizeConverter x:Key="sizeConv" />
    </Window.Resources>

    <Rectangle Fill="Blue" 
       Width="{Binding ElementName=window1, Path=MousePos.X}" 
       Height="{Binding ElementName=window1, Path=MousePos.Y}" 
     HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Window>

C#:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MyNamespace
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private Point _mousePos;

        public MainWindow()
        {
            InitializeComponent();
        }

        public event PropertyChangedEventHandler PropertyChanged;


        public Point MousePos
        {
            get { return _mousePos; }
            set
            {
                _mousePos = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("MousePos"));
            }
        }


        private void Grid1_MouseMove(object sender, MouseEventArgs e)
        {
            MousePos = e.GetPosition(window1);
        }
    }
}

Thanks in Advance!


Solution

  • If I understand well your problem, you want to draw a rectangle at the center of the window. The size of this rectangle is calculated based on the mouse pointer position. So that the mouse pointer is always in one of the corner of the rectangle.

    enter image description here

    The height of the rectangle is

    rect.Height = Math.Abs(mousePosition.Y - container.ActualHeight / 2) * 2
    

    The width of the rectangle is

    rect.Width = Math.Abs(mousePosition.X - container.ActualWidth / 2) * 2
    

    You need to create a ViewModel that contains properties

    public class MyRectContainerViewModel : BaseViewModel
    {
        private double _actualHeight;
        public double ActualHeight
        {
            get { return  _actualHeight; }
            set 
            {
                if (_actualHeight != value)
                {
                    _actualHeight = value;
                    RecalculateSize();
                }
            }
        }
    
        private double _actualWidth;
    
        public double ActualWidth
        {
            get { return _actualWidth; }
            set
            {
                if (_actualWidth != value)
                {
                    _actualWidth = value;
                    RecalculateSize();
                }
            }
        }
    
    
        private Point _mousePosition;
    
        public Point MousePosition
        {
            get { return _mousePosition; }
            set 
            {
                if (!value.Equals(_mousePosition))
                {
                    _mousePosition = value;
                    RecalculateSize();
                }
            }
        }
    
        public double RectHeight { get; private set; }
        public double RectWidth { get; private set; }
    
    
        private void RecalculateSize()
        {
            RectWidth = Math.Abs(MousePosition.X - ActualWidth / 2) * 2;
            RectHeight = Math.Abs(MousePosition.Y - ActualHeight / 2) * 2;
            OnPropertyChanged(nameof(RectHeight));
            OnPropertyChanged(nameof(RectWidth));
        }
    }
    

    The DataContext of the rectangle is the MyRectContainerViewModel.

    If you are using MVVM, you need to find a way to update ActualHeight and ActualWidth. ActualHeight

    Although it has an ActualHeightProperty backing field, ActualHeight does not raise property change notifications and it should be thought of as a regular CLR property and not a dependency property.

    Idem for the Mouse Position. You can use interactivity Example of use Binding Mouse position