So I try pass MyProperty from code-behind of View through Command to ViewModel. its looks like this:
View: code-behind .xaml.cs
public partial class MainWindow : Window
{
public string MyProperty { get; set; }
public MainWindow()
{
InitializeComponent();
}
private void Test_Click(object sender, RoutedEventArgs e)
{
MyProperty = "test click";
}
}
View: .xaml
<MenuItem Header="Test" CommandParameter="{Binding ElementName=MainWindow, Path=MyProperty}" Command="{Binding Test}" Click="Test_Click"></MenuItem>
ViewModel:
private RelayCommand _test;
public RelayCommand Test {
get
{
if (_test != null)
{
return _test;
}
return _test = new RelayCommand(obj =>
{
MessageBox.Show($"{obj}"); // here obj = null why?
});
}
}
RelayCommand:
internal 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)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
also tried instead of ElementName use RelativeSource but doesnt work:
<MenuItem Command="{Binding DataContext.Test, RelativeSource={RelativeSource AncestorType=views:MainWindow}}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=views:MainWindow}, Path=MyProp}" Click="Test_Click"></MenuItem>
My question is:
Binding only works on properties if you notify when the property value has changed. A simple property does not do any notification. Within a View you can declare a DependencyProperty
which will do the notification for the binding
public partial class MainWindow : Window
{
public string MyProperty
{
get { return (string)GetValue( MyPropertyProperty ); }
set { SetValue( MyPropertyProperty, value ); }
}
// Using a DependencyProperty as the backing store for MyPropertyB. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register( "MyProperty", typeof( string ), typeof( MainWindow ), new PropertyMetadata( null ) );
private void Button_Click( object sender, RoutedEventArgs e )
{
MyProperty = "From Button_Click";
}
}
<Window
...
x:Name="Root"
...>
...
<Button Command="{Binding Test}"
Content="Test"
Click="Button_Click"
CommandParameter="{Binding ElementName=Root, Path=MyProperty}" />
...
</Window>