0

I would like to know what is wrong with my data binding. Simply, when I click on an element, I must get the X and Y mouse position. It should reflect on the textboxes. BUt my code does not. Here is the XAML code:

<TextBox Name="positionX_txtbox" Width="58" Text="{Binding x,NotifyOnTargetUpdated=True,UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Name="positionY_txtbox" Width="58" Text="{Binding y,NotifyOnTargetUpdated=True,UpdateSourceTrigger=PropertyChanged}"/>

Here is the class that inherits from INotifyPropertyChanged:

public class VideoViewModel : INotifyPropertyChanged {
    private double _x;
    private double _y;

        public double x {
            get { return _x; }
            set {
                _x = value;
                OnPropertyChanged();
            }
        }

        public double y {
            get { return _y; }
            set {
                _y = value;
                OnPropertyChanged();
            }
        }

public event PropertyChangedEventHandler? PropertyChanged;

public void OnPropertyChanged([CallerMemberName] string propertyName = null) { 
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
}

This is the code that runs upon mouse click:

VideoViewModel VideoViewModel = new VideoViewModel();

private void Video_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
            Point point = e.GetPosition(null);            
            VideoViewModel.x = point.X;
            VideoViewModel.y = point.Y;
            DataContext = VideoViewModel;
        }

I know this is a beginner level question but I'm fairly new to C# and I'd appreciate any help.

  • try to set the datacontext earlier while initializing the viewmodel. if that does not work, please provide us your OnPropertyChanged() method and where you initialize your viewmodel – Tommehh Aug 12 '22 at 05:36
  • VideoViewModel VideoViewModel = new VideoViewModel(); is just outside of my Video_MouseLeftButtonDown function and is still within the same namespace. Could you elaborate more on 'setting the datacontext earlier'? – sean trees Aug 12 '22 at 05:57
  • As for the OnPropertyChanged, I edited my question above to include it. – sean trees Aug 12 '22 at 06:00
  • Please note that `NotifyOnTargetUpdated=True` and `UpdateSourceTrigger=PropertyChanged` on the Bindings is totally pointless. The Binding should just look like this: `Text="{Binding x}"`. – Clemens Aug 12 '22 at 07:10

1 Answers1

1

It works after setting the DataContext earlier.

Heres the MainWindow.xaml.cs I made (setting the DataContext after InitializeComponent()):

public MainWindow()
{
    InitializeComponent();
    VideoViewModel = new VideoViewModel();
    DataContext = VideoViewModel;
}

public VideoViewModel VideoViewModel { get; }

private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    Point point = e.GetPosition(null);
    VideoViewModel.x = point.X;
    VideoViewModel.y = point.Y;
}

Your Binding ist just fine just the timing of setting the DataContext isn't. Here an article about it: https://stackoverflow.com/a/7262322/11000908

My XAML looks like this:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <TextBox Grid.Row="0" Name="positionX_txtbox" Width="700" Height="50"
             Text="{Binding x}"/>
    <TextBox Grid.Row="1" Name="positionY_txtbox" Width="700" Height="50"
             Text="{Binding y}"/>
    <TextBlock Grid.Row="2" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" >Press mouse button</TextBlock>
</Grid>

And my VideoViewModel Class like this:

public class VideoViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    private double _x;
    private double _y;

    public double x
    {
        get { return _x; }
        set
        {
            _x = value;
            OnPropertyChanged();
        }
    }

    public double y
    {
        get { return _y; }
        set
        {
            _y = value;
            OnPropertyChanged();
        }
    }

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

Btw since you are new to C#. Coding conventions suggest writing properties like your x and y with a capital letter. And in a real project I wouldn't just call them x and y, maybe something like MousePositionX and MousePositionY. But those are details.

Clemens
  • 123,504
  • 12
  • 155
  • 268
  • There is no reason to make ViewModel a public property of the MainWindow class. It would work as well with the private field. – Clemens Aug 12 '22 at 07:14