The problem is in your method:
e.Text gives the character typed and not the content of TextBox
so this solution gives the result waited:
    private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
    {
        Regex regex = new Regex("^-?[0-9]*[\\.,]?[0-9]?[0-9]?$");
        var futureText = $"{(sender as TextBox).Text}{e.Text}";
        e.Handled = !regex.IsMatch(futureText);
    }
To replace , by .  i suggest you to add the TextChanged event:
    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        var myInput = sender as TextBox;
        myInput.Text = myInput.Text.Replace(",", ".").Trim();
        myInput.CaretIndex = myInput.Text.Length;
    }
   <TextBox PreviewTextInput="NumberValidationTextBox" TextChanged="OnTextChanged"/>
i play with the property CaretIndex  to keep the Cursor in last position (Replace resets the position of Cursor in first position)
And i have added .trim() to myInput.Text = myInput.Text.Replace(",", ".").Trim(); because previewtextInput event doesnt play with space (its normal)