I need to change label value when clicking on a button so it will say "Please wait".
That button have a command, but since the command doesn't know the window controls I can't refer to them from the command.
For a reference, this is the label:
<Label Content="{Binding EuroCurrentRate}" Margin="450,226,672,351" x:Name="EurLabel" Foreground="White" FontSize="22" >
And this the command :
class EuroClickCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
var viewModel = (RTViewModel)parameter;
viewModel.OpenGraph();// When button is pushed fire this function
}
}
The property in the ViewModel:
public ICommand ButtonClickCommand
{
get
{
return new EuroClickCommand();
}
}
public void OpenGraph()//Fire commands by button binding and command mechanism
{
AreaChart.MainWindow myWindow = new AreaChart.MainWindow();
myWindow.Show();
}
How should I change the label content from the command ?
Label has binding to a viewmodel property:
<Label Content="{Binding EuroCurrentRate}" .../>
change that property in command method:
public void Execute(object parameter)
{
var viewModel = (RTViewModel)parameter;
viewModel.EuroCurrentRate = "Please wait";
viewModel.OpenGraph();// When button is pushed fire this function
}
or more likely EuroCurrentRate = "Please wait"; should be done in OpenGraph() method
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));
}
}
The following code is working for usercontrols but not in the Mainwindows. Setting Focusable="True" for the mainwindow.
<Window.InputBindings>
<KeyBinding Modifiers="Ctrl" Key="S" Command="{Binding SaveCommand}" />
</Window.InputBindings>
private ICommand _saveCommand;
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
{
_saveCommand = new RelayCommand(
param => this.SaveObject(),
param => this.CanSave()
);
}
return _saveCommand;
}
}
private bool CanSave()
{
return (Project != null);
}
private void SaveObject()
{
// Code here
}
Got fixed by using the below code from the link.
Keyboard shortcuts in WPF
public YourWindow() //inside any WPF Window constructor
{
...
//add this one statement to bind a new keyboard command shortcut
InputBindings.Add(new KeyBinding( //add a new key-binding, and pass in your command object instance which contains the Execute method which WPF will execute
new WindowCommand(this)
{
ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate
}, new KeyGesture(Key.P, ModifierKeys.Control)));
...
}
Create a simple WindowCommand class which takes an execution delegate to fire off any method set on it.
public class WindowCommand : ICommand
{
private MainWindow _window;
//Set this delegate when you initialize a new object. This is the method the command will execute. You can also change this delegate type if you need to.
public Action ExecuteDelegate { get; set; }
//You don't have to add a parameter that takes a constructor. I've just added one in case I need access to the window directly.
public WindowCommand(MainWindow window)
{
_window = window;
}
//always called before executing the command, mine just always returns true
public bool CanExecute(object parameter)
{
return true; //mine always returns true, yours can use a new CanExecute delegate, or add custom logic to this method instead.
}
public event EventHandler CanExecuteChanged; //i'm not using this, but it's required by the interface
//the important method that executes the actual command logic
public void Execute(object parameter)
{
if (ExecuteDelegate != null)
{
ExecuteDelegate();
}
else
{
throw new InvalidOperationException();
}
}
}
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 bind some values to WPF listview.I want to remove or hide some row when click or select in row.I m try to do this one as follow.
listview.Items.RemoveAt(listview.Items.IndexOf(listview.SelectedItem));
but it's get exception.how to do this one? please help me......
You can use MVVM pattern to achive it. You will need to create ObservableCollection, and then you can write command, wich will initialize with its collection, and when it should execute, it recieve object you need to delete via {Binding}. Its look like this:
//View model
public class FileGroupViewModel : ModelObject
{
private ObservableCollection<FileGroup> fileGroups;
public FileGroupViewModel ( ObservableCollection<FileGroup> _initialFileGroup )
{
this.fileGroups = _initialFileGroup;
}
public ObservableCollection<FileGroup> FileGroups
{
get
{
return fileGroups;
}
set
{
fileGroups = value;
}
}
public ICommand DeleteFileGroup
{
get
{
return new RemoveItemCommand<FileGroup>(FileGroups);
}
}
}
RemoveItemCommand - is templated class which implements ICommand interface
public class RemoveItemCommand<T> : ICommand
{
private ObservableCollection<T> _items;
public RemoveItemCommand(ObservableCollection<T> items)
{
_items = items;
}
public void Execute(object parameter)
{
_items.Remove((T)parameter);
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
then, your view will contain something like this^
<DataTemplate>
<Button Command="{StaticResource DeleteCommand}" CommandParameter="{Binding}" Text="{Binding}" />
</DataTemplate>
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}"