I am using MVVM pattern. I have a
Text box whose Text property is bound to ViewModel's(VM supports INotifyProperyChange) Text property
Button whose command is bound to VM's ICommand property type
You may think of this as a SearchTextBox and SearchButton
The problem I am facing is that when I enter the text in SearchTextBox and click on SearchButton then only the SearchTextBox bound set property implementation is called but the Command for SearchButton click never executes (Note: ICommand CanExecute handler always returns True)
It works fine if I either tab out of SearchTextBox using TAB key or use mouse to move focus away from SearchTextBox and then click the SearchButton. That means do two seperate actions to trigger both the events seperately. Ideally clicking on the SearchButton should result in the SearchTextBox loose focus thus calling Set property and the click on the Search button translates into the command execution.
Code is as below
XAML:
<TextBox Text="{Binding Path=SearchText,Mode=TwoWay}"/>
<Button Content="Search" Width="100" Command="{Binding MySearchCommand}"/>
C#:
public String _SearchText;
public String SearchText
{
get { return _SearchText; }
set
{
_SearchText = value;
OnPropertyChanged("SearchText");
}
}
ICommand implementation is a standard implemenetation with no fancy code and CanExecute handler always returns True
Try to isolate the issue by writing a small test project that reproduces the issue, if you can repro then please post the code. Usually when you repro the issue outside of your main project the problem and the solution become obvious.
I created a sample application to reproduce this problem.
I placed breakpoint and added a Debug.Writeline in SearchText - Set property and MySearchCommandExecute method.
When breakpoints are set, only the SearchText - Set property gets called. I observed that if I remove the breakpoint from SearchText - Set property then both the property and the command are correctly executed. Looks like some problem with VS 2008 but I may be wrong.
The relevant sample code is as below
class SearchViewModel : ViewModelBase
{
public SearchViewModel()
{
}
public String _SearchText;
public String SearchText
{
get { return _SearchText; }
set
{
System.Diagnostics.Debug.WriteLine("Set Membership called");
OnPropertyChanged("SearchText");
}
}
#region Commands
RelayCommand _SearchCommand;
public ICommand SearchCommand
{
get
{
if (_SearchCommand == null)
{
_SearchCommand = new RelayCommand(param => this.MySearchCommandExecute(), param => this.MySearchCommandCanExecute);
}
return _SearchCommand;
}
}
public void MySearchCommandExecute()
{
System.Diagnostics.Debug.WriteLine("MySearchCommandExecute called");
// Do Search
}
public bool MySearchCommandCanExecute
{
get
{
return true;
}
}
#endregion
}
SearchView.xaml
<UserControl x:Class="WpfApplication2.SearchView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<StackPanel>
<StackPanel Orientation="Vertical" HorizontalAlignment="Left" Margin="4">
<Label Foreground="Black" FontFamily="Calibri" Width="155" Margin="4,0,4,0" Content="SearchText"/>
<TextBox Foreground="Black" FontFamily="Calibri" Width="155" Margin="4,0,4,0" Text="{Binding Path=SearchText}"/>
</StackPanel>
<Button HorizontalAlignment="Left" Content="Search" Width="100" Command="{Binding SearchCommand}" Margin="8"/>
</StackPanel>
</UserControl>
RelayCommand.cs
// Reference: MSDN sample
class RelayCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("relaycommand execute");
_execute = execute;
_canExecute = canExecute;
}
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
Byte,
Sorry for my late response, but I hope it will become handy anyway. I'm very busy lately so I couldn't debug your code (I'll try to do that when I have more time), but please try my sample code pasted below (It works perfectly for me). As you can see it's extremely simple. I used your xaml, but for Window:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new TempViewModel();
}
}
public class TempViewModel : INotifyPropertyChanged
{
private String _searchText;
private ICommand _searchCommand;
#region Commands
protected class Search : ICommand
{
private TempViewModel _viewModel;
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
public void Execute(object parameter)
{
//MessageBox in VM is just for demonstration
MessageBox.Show("command executed with search string: " + this._viewModel._searchText);
}
public Search(TempViewModel viewModel)
{
this._viewModel = viewModel;
}
}
#endregion //Commands
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(String propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion //INotifyPropertyChanged
#region Public properties
public String SearchText
{
get
{
return this._searchText;
}
set
{
this._searchText = value;
OnPropertyChanged("SearchText");
}
}
public ICommand SearchCommand
{
get
{
return this._searchCommand;
}
set
{
this._searchCommand = value;
OnPropertyChanged("SearchCommand");
}
}
#endregion //Public properties
public TempViewModel()
{
this.SearchCommand = new Search(this);
this.SearchText = "Sample string";
}
}
Please feel free to ask if you have any further questions.
EDIT: Ah, sorry, but I changed Command="{Binding SearchCommand}" to Command="{Binding Path=SearchCommand}"
Related
I have two menu items, "message", and "check". "Check" is Checkable and have a checkbox near the header. I want, by clicking on Check to uncheck it, and disable the "message" item.
Also, I want to do it by both clicking, and using a shortcut.
I wrote some additional classes like RelayCommand
public class RelayCommand : ICommand
{
private Action<object> _execute;
private Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_canExecute = canExecute;
_execute = execute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
Observable object (which is analogue of INotifyOnPropertyChanged)
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
and MainViewModel class
public class MainViewModel : ObservableObject
{
private readonly MainWindow _mainWindow;
private bool _isChecked { get; set; } = true;
public bool IsChecked
{
get
{
return _isChecked;
}
set
{
_isChecked = value;
OnPropertyChanged();
}
}
public RelayCommand Check { get; set; }
public MainViewModel(MainWindow mainwindow)
{
_mainWindow = mainwindow;
IsChecked = false;
Check = new RelayCommand(o =>
{
if (IsChecked == false)
{
_mainWindow.Message_menu_item.IsEnabled = true;
IsChecked = true;
}
else
{
_mainWindow.Message_menu_item.IsEnabled = false;
IsChecked = false;
}
});
}
}
My xaml
<MenuItem Header="File">
<MenuItem
Name="Message_menu_item"
InputGestureText="Ctrl+M"
Header="_Message"/>
<MenuItem
Name="Check_menu_item"
InputGestureText="Ctrl+C"
Command="{Binding Check}"
Header="Check"
IsCheckable="True"
IsChecked="{Binding IsChecked}"/>
<Separator />
<MenuItem Header="Exit"
InputGestureText="Ctrl+E"/>
</MenuItem>
And binding
<KeyBinding Key="C" Modifiers="Ctrl" Command="{Binding Check}"/>
I wanted to start an app with checked checkbox and available Message menu item, but it is starting unchecked, and by clicking it, it simply disabling the message, and ignoring the checkbox (it only work ones, clicking on it again doesn't change anything). It only works fine using the shortcut, BUT I can only use shortcut after clicking the menu dropdown button "file" in my case (like this, and if it is closed shortcut doesn't work )
I don't understand why is it working so weird, please help.
I wanted to start an app with checked checkbox
If so, you should change the initialization IsChecked = false; in your viewmodel constructor accordingly.
The weird behaviour of the checkbox is a result of modifying IsChecked from the Check command plus binding it to the IsChecked property of the menu item without specifying a mode (which results in a two way binding). So, when using the menu, the property is toggled twice: via command and via the binding. Using the key binding works, because it only triggers the command.
To solve this, either change the binding mode to OneWay or don't change the property value in the command.
Furthermore: You should remove the reference to the window from your viewmodel. This can be achieved by binding the IsEnabled property of the message menu item to another property on your viewmodel like this:
public bool IsMessageMenuEnabled => !this.IsChecked;
public bool IsChecked
{
get => this.isChecked;
set
{
this.isChecked = value;
this.OnPropertyChanged();
this.OnPropertyChanged(nameof(this.IsMessageMenuEnabled));
}
}
I am struggling with this for a while and I cannot figure it out. I have a button and a textBox. The textBox is linked to a property named: MessageDisplay. I want to be able to access this property and update the textBox in several places. Sadly, the PropertyChanged is null. The weird thing is that if I copy/paste the MessageDisplayModel class into the *MessageViewModel * class, it works ...
here is my code :
XAMLfile :
<Grid>
<Button Command="{Binding DisplayTextCommand}" Name="DisplayTextCommand" Margin="53,72,544.6,286" Width="Auto">Push</Button>
<TextBox Name="MessageDisplay" Text="{Binding MessageDisplay, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</Grid>
MessageDisplayModel file
public class MessageDisplayModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _message;
public string MessageDisplay
{
get { return _message; }
set
{
this._message = value;
this.OnPropertyChanged("MessageDisplay");
}
}
public void UpdateTextBox(string output)
{
MessageDisplay = output;
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
}//class
MessageViewModel file:
public class MessageViewModel
{
private ICommand _testCommand;
public MessageDisplayModel MessageDisplaySmt = new MessageDisplayModel();
public ICommand DisplayTextCommand
{
get
{
return new DelegateCommand(DisplayMessage);
}
set
{
if (_testCommand == value) return;
_testCommand = value;
}
}
public void DisplayMessage()
{
MessageDisplaySmt.UpdateTextBox("Successfuly downloaded");
}
}//class
MainWindow file
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MessageDisplay.DataContext = new MessageDisplayModel();
DisplayTextCommand.DataContext = new MessageViewModel();
}
}//class
I update the MessageDisplay property by using the method UpdateTextBox(string). I call this method on the click of the button. When debugging the property gets updated but when time comes to notify the UI that the property has changed, PropertyChangedEventHandler PropertyChanged has its value null ... But if I write something in the textBox, the PropertyChangedEventHandler PropertyChanged gets changed and isn't null anymore. All I want is to be able to change the textBox's property whenever I want and from anywhere I want to.
Thank you
You are using two different instances of MessageDisplayModel. You must use a shared instance.
Also the DisplayTextCommand is implemented "wrong". The set method is redundant as the property's get always returns a new instance of the ICommand.
MessageViewModel.cs
public class MessageViewModel
{
pulic MessageViewModel()
{
}
pulic MessageViewModel(MessageDisplayViewModel messageDisplayViewModel)
{
this.MessageDisplaySmt = messageDisplayViewModel;
}
public void DisplayMessage()
{
this.MessageDisplaySmt.UpdateTextBox("Successfuly downloaded");
}
public MessageDisplayViewModel MessageDisplaySmt { get; set; }
public ICommand DisplayTextCommand { get => new DelegateCommand(DisplayMessage); }
}
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Alternatively use XAML to set the DataContext (see MainWindow.xaml). Would require a parameterless constructor.
this.DataContext = new MessageViewModel(new MessageDisplayViewModel());
}
}
MainWindow.xaml
<Window>
<!--
Alternative DataContext declaration using XAML instead of C#.
Requires a parameterless constructor for both view model objects.
-->
<Window.DataContext>
<MessageViewModel>
<MessageViewModel.MessageDisplaySmt>
<MessageDisplayViewModel />
</MessageViewModel.MessageDisplaySmt>
</MessageViewModel>
</Window.DataContext>
<StackPanel>
<Button Command="{Binding DisplayTextCommand}"
Content="Push" />
<TextBox Text="{Binding MessageDisplaySmt.MessageDisplay}" />
</StackPanel>
</Window>
So i have WPF application with main windoes and 2 UserControls:
HomeView.xaml
OptionsView.xaml
View Model
public class ApplicationViewModel : INotifyPropertyChanged
{
#region Fields
private ICommand changePageCommand;
private ICommand addFilesCommand;
private IPageViewModel _currentPageViewModel;
private List<IPageViewModel> _pageViewModels;
#endregion
public ApplicationViewModel()
{
// Add available pages
PageViewModels.Add(new HomeViewModel() { IsSelected = true });
PageViewModels.Add(new OptionsViewModel() { IsSelected = false });
// Set starting page
CurrentPageViewModel = PageViewModels[0];
}
#region Properties / Commands
public ICommand ChangePageCommand
{
get
{
if (changePageCommand == null)
{
changePageCommand = new RelayCommand(
p => ChangeViewModel((IPageViewModel)p),
p => p is IPageViewModel);
}
return changePageCommand;
}
}
public List<IPageViewModel> PageViewModels
{
get
{
if (_pageViewModels == null)
_pageViewModels = new List<IPageViewModel>();
return _pageViewModels;
}
}
public IPageViewModel CurrentPageViewModel
{
get
{
return _currentPageViewModel;
}
set
{
if (_currentPageViewModel != value)
{
_currentPageViewModel = value;
OnPropertyChanged("CurrentPageViewModel");
}
}
}
#endregion
#region Methods
private void ChangeViewModel(IPageViewModel viewModel)
{
if (!PageViewModels.Contains(viewModel))
PageViewModels.Add(viewModel);
CurrentPageViewModel = PageViewModels.FirstOrDefault(vm => vm == viewModel);
}
#endregion
}
Whan application start
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow app = new MainWindow();
ApplicationViewModel context = new ApplicationViewModel();
app.DataContext = context;
app.Show();
}
}
Windows respurces
<Window.Resources>
<DataTemplate DataType="{x:Type home:HomeViewModel}">
<home:HomeView />
</DataTemplate>
<DataTemplate DataType="{x:Type options:OptionsViewModel}">
<options:OptionsView />
</DataTemplate>
</Window.Resources>
And inside HomeView.xaml i have simple button:
<Button Command="{Binding DataContext.AddFilesCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding}"/>
And i want to add simple Click command, something.
So i try to add this ICommand:
public ICommand AddFilesCommand
{
}
Any suggestions how to add this kind on command that will execute after each Button Click ?
This can be done a lot easier. I would create a class to implement commands easily:
using System;
using System.Windows.Input;
namespace YourNameSpace
{
public class RelayCommand : ICommand
{
private Action Action;
public Command(Action _action)
{
Action = _action;
}
public event EventHandler CanExecuteChanged = (sender, e) => { };
public bool CanExecute(object parameter) => true;
public void Execute(object parameter)
{
Action();
}
}
}
Then create the command (you don't need private ICommand for this):
public ICommand AddFileCommand { get; set; }
And use it like this (in the constructor):
AddFileCommand = new RelayCommand(()=>
{
MethodToExecute();
});
XAML:
<Button Command="{Binding AddFileCommand}"/>
This way your code will be easier to see trough.
I am trying to attach a command and a commandparameter to a textbox on return key but without success. The parameter is the current text in the same textbox.
<TextBox x:Name="txtSearch">
<TextBox.InputBindings>
<KeyBinding Command="{Binding SearchCommand}"
CommandParameter="{Binding Path=Text, ElementName=txtSearch}" Key="Return" />
</TextBox.InputBindings>
</TextBox>
Basically I want to execute the command when user clicks on return/enter key and pass as a parameter the current text in the textbox.
I have found this link where it is said that in .NET 3.5 command parameter for keybinding is not accepting bindings. So a solution is proposed by code in code-behind but how can I pass a parameter to the command from the code?
First, you'll need to add the KeyBinding to your TextBox and set its Command on code-behind. Just add this in the constructor of your View:
public MainWindow()
{
InitializeComponent();
DataContext = new MyViewModel();
KeyBinding kb = new KeyBinding();
kb.Command = (DataContext as MyViewModel).SearchCommand;
kb.Key = Key.Enter;
txtSearch.InputBindings.Add(kb);
}
Then, you can bind the Text property of the TextBox named txtSearch to a property of your ViewModel. This way you don't need to pass a parameter as you can use the value of that property in your ViewModel inside the code that executes your Command.
Your ViewModel should look like this:
public class MyViewModel : ObservableObject
{
private string _txtSearch;
public string TxtSearch
{
get { return _txtSearch; }
set
{
if (value != _txtSearch)
{
_txtSearch = value;
OnPropertyChanged("TxtSearch");
}
}
}
private ICommand _searchCommand;
public ICommand SearchCommand
{
get
{
if (_searchCommand == null)
{
_searchCommand = new RelayCommand(p => canSearch(), p => search());
}
return _searchCommand;
}
}
private bool canSearch()
{
//implement canExecute logic.
}
private void search()
{
string text = TxtSearch; //here you'll have the string that represents the text of the TextBox txtSearch
//DoSomething
}
}
If you have access to C# 6 (Visual Studio 2015 and later versions), you can alter the call to the OnPropertyChanged to: OnPropertyChanged(nameof(TxtSearch));. This way you get rid of the "magic string" and eventual renaming of the property won't cause any problem for you.
And then your XAML should look like this: (Notice that you need to specify that te UpdateSourceTrigger must be PropertyChanged, so that your TxtSearch property of your ViewModel stays up to date when you hit the Enter key on your TextBox.
<TextBox Text="{Binding TxtSearch, UpdateSourceTrigger=PropertyChanged}" x:Name="txtSearch"/>
Your ViewModel needs to implement INotifyPropertyChanged and you need a proper ICommand implementation. Here I'll use the RelayCommand.
Those implementations are shown below.
Since your framework is .NET 3.5, implement it like this:
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
This is a implementation of the RelayCommand:
public class RelayCommand : ICommand
{
private Predicate<object> _canExecute;
private Action<object> _execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
_canExecute = canExecute;
_execute = execute;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
I have two TextBoxes inside my View on which I am trying to implement a simple validation using MVVM design pattern.The issue is even when my ViewModel is implementing Inotification Changed interface and the property is bound tot the text property of the TextBox,on entering text propertyChange event never fires.I don't know where I have gone wrong.Please help.Its been bugging me for quite a while.
ViewModel :
class TextBoxValidationViewModel : ViewModelBase, IDataErrorInfo
{
private readonly TextBoxValidationModel _textbxValModel;
private Dictionary<string, bool> validProperties;
private bool allPropertiesValid = false;
private DelegateCommand exitCommand;
private DelegateCommand saveCommand;
public TextBoxValidationViewModel(TextBoxValidationModel newTextBoxValObj)
{
this._textbxValModel = newTextBoxValObj;
this.validProperties = new Dictionary<string, bool>();
this.validProperties.Add("BuyTh", false);
this.validProperties.Add("SellTh", false);
}
public string BuyTh
{
get { return _textbxValModel.BuyTh; }
set
{
if (_textbxValModel.BuyTh != value)
{
_textbxValModel.BuyTh = value;
base.OnPropertyChanged("BuyTh");
}
}
}
public string SellTh
{
get { return _textbxValModel.SellTh; }
set
{
if (_textbxValModel.SellTh != value)
{
_textbxValModel.SellTh = value;
base.OnPropertyChanged("SellTh");
}
}
}
public bool AllPropertiesValid
{
get { return allPropertiesValid; }
set
{
if (allPropertiesValid != value)
{
allPropertiesValid = value;
base.OnPropertyChanged("AllPropertiesValid");
}
}
}
public string this[string propertyName]
{
get
{
string error = (_textbxValModel as IDataErrorInfo)[propertyName];
validProperties[propertyName] = String.IsNullOrEmpty(error) ? true : false;
ValidateProperties();
CommandManager.InvalidateRequerySuggested();
return error;
}
}
public string Error
{
get
{
return (_textbxValModel as IDataErrorInfo).Error;
}
}
public ICommand ExitCommand
{
get
{
if (exitCommand == null)
{
exitCommand = new DelegateCommand(Exit);
}
return exitCommand;
}
}
public ICommand SaveCommand
{
get
{
if (saveCommand == null)
{
saveCommand = new DelegateCommand(Save);
}
return saveCommand;
}
}
#region private helpers
private void ValidateProperties()
{
foreach (bool isValid in validProperties.Values)
{
if (!isValid)
{
this.AllPropertiesValid = false;
return;
}
}
this.AllPropertiesValid = true;
}
private void Exit()
{
Application.Current.Shutdown();
}
private void Save()
{
_textbxValModel.Save();
}
}
}
#endregion
Model :
class TextBoxValidationModel : IDataErrorInfo
{
public string BuyTh { get; set; }
public string SellTh { get; set; }
public void Save()
{
//Insert code to save new Product to database etc
}
public string this[string propertyName]
{
get
{
string validationResult = null;
switch (propertyName)
{
case "BuyTh":
validationResult = ValidateName();
break;
case "SellTh":
validationResult = ValidateName();
break;
default:
throw new ApplicationException("Unknown Property being validated on Product.");
}
return validationResult;
}
}
public string Error
{
get
{
throw new NotImplementedException();
}
}
private string ValidateName()
{
return "Entered in validation Function";
}
}
}
ViewModelBase abstract Class :
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
Application Start event code:
private void Application_Startup(object sender, StartupEventArgs e)
{
textboxvalwpf.Model.TextBoxValidationModel newTextBoxValObj = new Model.TextBoxValidationModel();
TextBoxValidation _txtBoxValView = new TextBoxValidation();
_txtBoxValView.DataContext = new textboxvalwpf.ViewModel.TextBoxValidationViewModel(newTextBoxValObj);
// _txtBoxValView.Show();
}
}
View Xaml code:
<Window x:Class="textboxvalwpf.TextBoxValidation"
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:c="clr-namespace:textboxvalwpf.Commands"
xmlns:local="clr-namespace:textboxvalwpf"
mc:Ignorable="d"
Title="TextBoxValidation" Height="300" Width="300">
<Grid>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="86,44,0,0" TextWrapping="Wrap" Text="{Binding Path=BuyTh, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="textBox1" HorizontalAlignment="Left" Height="23" Margin="88,121,0,0" TextWrapping="Wrap" Text="{Binding Path=SellTh,ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
<Label x:Name="label_BuyTh" Content="Buy Th" HorizontalAlignment="Left" Margin="10,44,0,0" VerticalAlignment="Top" Width="71"/>
<Label x:Name="label_SellTh" Content="Sell Th" HorizontalAlignment="Left" Margin="10,117,0,0" VerticalAlignment="Top" Width="71"/>
</Grid>
</Window>
In App.xaml, you'll find a StartupUri attribute. By default, it looks like this:
<Application x:Class="WPFTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFTest"
StartupUri="MainWindow.xaml">
If you renamed MainWindow.xaml to TextBoxValidation.xaml, as I think you did, it'll look like this:
StartupUri="TextBoxValidation.xaml">
Your application will automatically create an instance of that StartupUri window and show it. That'll be the application's main window, so the application will shut down when it closes.
That instance won't have a viewmodel, because nothing in your code gives it one. You are creating your own instance of the window, giving it a viewmodel, and then doing nothing with it because another instance is being shown. I imagine you thought just creating the window was enough to show it, but that's not what's happening at all. Before you commented out the Show() call, you did have one window with a working viewmodel that did the validation and updated the viewmodel properties.
Let the App create the window the way it wants to.
A quick, simple fix is to delete that Startup event handler from App and move your viewmodel creation code into TextBoxValidation's constructor:
public TextBoxValidation()
{
InitializeComponent();
textboxvalwpf.Model.TextBoxValidationModel newTextBoxValObj = new Model.TextBoxValidationModel();
this.DataContext = new textboxvalwpf.ViewModel.TextBoxValidationViewModel(newTextBoxValObj);
}