WPF Ribbon RibbonCommand replaced by ICommand - wpf

I'm looking for an example how to replace this old code for RibbonApplicationMenuItem. Question is how to replace removed RibbonCommand
<ResourceDictionary>
<r:RibbonCommand
x:Key="MenuItem1"
CanExecute="RibbonCommand_CanExecute"
LabelTitle="Menu Item 1"
LabelDescription="This is a sample menu item"
ToolTipTitle="Menu Item 1"
ToolTipDescription="This is a sample menu item"
SmallImageSource="Images\files.png"
LargeImageSource="Images\files.png" />
</ResourceDictionary>
</r:RibbonWindow.Resources>
<r:RibbonApplicationMenuItem Command="{StaticResource MenuItem1}">
</r:RibbonApplicationMenuItem>

You can use RelayCommand.
Binding in this case is very simple:
<ribbon:RibbonApplicationMenuItem Header="Hello _Ribbon"
x:Name="MenuItem1"
ImageSource="Images\LargeIcon.png"
Command="{Binding MyCommand}"
/>
Your ViewModel class in this case, must contain property MyCommand of ICommand type:
public class MainViewModel
{
RelayCommand _myCommand;
public ICommand MyCommand
{
get
{
if (_myCommand == null)
{
_myCommand = new RelayCommand(p => this.DoMyCommand(p),
p => this.CanDoMyCommand(p));
}
return _myCommand;
}
}
private bool CanDoMyCommand(object p)
{
return true;
}
private object DoMyCommand(object p)
{
MessageBox.Show("MyCommand...");
return null;
}
}
Don't forget assign DataContext of MainWindow:
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
RelayCommand class:
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
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);
}
#endregion // ICommand Members
}

Related

Datagrid don't show elements MVVM

I am trying to load a list in my datagrid when pressing the button but it does not show anything.
Do you know where the error is?
Thanks a lot
<UserControl x:Class="HiberusHubClient.View.RatesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:HiberusHubClient.View"
mc:Ignorable="d"
x:Name="RatesViewControl"
d:DesignHeight="450" d:DesignWidth="800"
DataContext="RatesViewControlDataContext">
<Grid>
<StackPanel HorizontalAlignment = "Left">
<Button x:Name="btnUpdate" Width="100" Height="20" HorizontalAlignment="Center" Grid.Row="1" Content="Update" Command="{Binding Path=UpdateCommand}" />
<StackPanel Orientation = "Horizontal">
<DataGrid Width="200" Height="400" AutoGenerateColumns="True" ItemsSource="{Binding LstConvertRates,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Name="lstDataGrid" />
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
public partial class RatesView : UserControl
{
public RatesView()
{
InitializeComponent();
DataContext = new ConvertRatesViewModel();
}
}
ConvertRate.cs
public class ConvertRate
{
}
public class ConvertRates : INotifyPropertyChanged
{
private string currencyFrom;
private string currencyTo;
private string rate;
public string CurrencyFrom
{
get
{
return currencyFrom;
}
set
{
if (currencyFrom != value)
{
currencyFrom = value;
RaisePropertyChanged("CurrencyFrom");
}
}
}
public string CurrencyTo
{
get { return currencyTo; }
set
{
if (currencyTo != value)
{
currencyTo = value;
RaisePropertyChanged("CurrencyTo");
}
}
}
public string Rate
{
get { return rate; }
set
{
if (rate != value)
{
rate = value;
RaisePropertyChanged("Rate");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
ConvertRatesViewModel .cs
internal class ConvertRatesViewModel : INotifyPropertyChanged
{
private ObservableCollection<ConvertRates> lstConvertRates;
public ObservableCollection<ConvertRates> LstConvertRates
{
get
{
return lstConvertRates;
}
set
{
lstConvertRates = value;
//if u want Observable Collection to get updated on edit either
RaisePropertyChanged("LstConvertRates");
}
}
public void getConvertRates()
{
HiberusHubeReference.RequestHubeRestService hiberusHubeReference = new HiberusHubeReference.RequestHubeRestService();
JavaScriptSerializer json = new JavaScriptSerializer();
string aa = json.Serialize(hiberusHubeReference.RequestRates());
ObservableCollection<ConvertRates> oMycustomclassname = Newtonsoft.Json.JsonConvert.DeserializeObject<ObservableCollection<ConvertRates>>(aa);
LstConvertRates = oMycustomclassname;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
private ICommand mUpdater;
public ICommand UpdateCommand
{
get
{
if (mUpdater == null)
mUpdater = new Updater();
return mUpdater;
}
set
{
mUpdater = value;
}
}
}
internal class Updater : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
ConvertRatesViewModel convertRatesViewModel = new ConvertRatesViewModel();
convertRatesViewModel.getConvertRates();
}
}
If you set DataContext in code behind then there is no need to set DataContext also in xaml. You can remove DataContext="RatesViewControlDataContext" from RatesView.xaml. Btw. DataContext="RatesViewControlDataContext" means DataContext property is set to string "RatesViewControlDataContext". You probably don't this.
Try to use existing implementation of ICommand interface like RelayCommand.
public class RelayCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
_canExecute = canExecute;
_execute = execute;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
For your UpdateCommand you can modify the setter and create a new instance of RelayCommand. In the constructor you can specify whether the command should be executed and which method on your ConvertRatesViewModel will be called when you press btnUpdate button.
private ICommand mUpdater;
public ICommand UpdateCommand
{
get
{
if (mUpdater == null)
mUpdater = new RelayCommand(x => true, x => getConvertRates());
return mUpdater;
}
set
{
mUpdater = value;
}
}

Input Binding CommandParameter Bind to Window

I want to have a window level KeyBinding with command paramter as window itself.
e.g.
<KeyBinding Command="{Binding CloseCommand}" CommandParameter="{Binding ElementName=mainWindow}" Key="Esc"/>
Binding works, but paramter comes in as null. What's the work around?
Following is my Command:`
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("Action excute is null");
_execute = execute;
_canExecute = canExecute;
}
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
Actually this working for me - but i am using the RelayCommand<FrameworkElement> of [MVVM Light Toolkit1.
<Window.InputBindings>
<KeyBinding Command="{Binding MyCommand, ElementName=MainRoot}" CommandParameter="{Binding ElementName=MainRoot}" Key="Esc"/>
</Window.InputBindings>
In my case the Command comes from a DependencyProperty, but that shouldn't make a big difference.
public RelayCommand<FrameworkElement> MyCommand
{
get { return (RelayCommand<FrameworkElement>)GetValue(MyCommandProperty); }
set { SetValue(MyCommandProperty, value); }
}
// Using a DependencyProperty as the backing store for MyCommand. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyCommandProperty =
DependencyProperty.Register("MyCommand", typeof(RelayCommand<FrameworkElement>), typeof(MainWindow), new PropertyMetadata(null));
public MainWindow()
{
InitializeComponent();
MyCommand = new RelayCommand<FrameworkElement>(DoSthYo);
}
public void DoSthYo(FrameworkElement fwE)
{
var x = fwE;
}
So because this is working - i think its your Command that does not support CommandParameter maybe.
My advice is to use a RelativeSource in your CommandParameter binding:
<Window.InputBindings>
<KeyBinding Command="{x:Static local:CloseWindowCommand.Instance}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Key="Esc" />
</Window.InputBindings>
In this way your binding can be independant from the name of your Window.
Then you can create a static command for closing each window of your application:
public class CloseWindowCommand : ICommand
{
public static readonly ICommand instance = new CloseWindowCommand();
public event EventHandler CanExecuteChanged;
private CloseWindowCommand()
{
}
public bool CanExecute(object parameter)
{
return (parameter is Window);
}
public void Execute(object parameter)
{
Window win;
if (CanExecute(parameter))
{
win = (Window)parameter;
win.Close();
}
}
}
I hope it can help you.

What if CanExecute has to be a method, and not a property?

So I have this View:
<StackPanel>
<TextBox x:Name="Name"/>
<Button x:Name="SayHello"
Content="Click Me" />
</StackPanel>
And I have this ViewModel:
internal class ShellViewModel : PropertyChangedBase
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
NotifyOfPropertyChange(() => Name);
NotifyOfPropertyChange(() => CanSayHello());
}
}
public bool CanSayHello()
{
bool isenabled = !string.IsNullOrWhiteSpace(Name);
return isenabled;
}
public void SayHello()
{
MessageBox.Show(string.Format("Hello, {0}!", Name));
}
}
But whenever I enter some value in the textbox, I got this exception:
{"Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 'System.Linq.Expressions.MemberExpression'."}
In the commercial app that I'm developing I must have the CanSayHello() member in the VM as a method, not as a property. What should I do?
You have that exception because you are calling NotifyOfPropertyChange on CanSayHello and CanSayHello is a method, not a property.
Change to:
public bool CanSayHello
{
get { return !string.IsNullOrWhiteSpace(Name); }
}
You should use commands to bind actions to UI items. There is an implementation of ICommand called RelayCommand which is typically used in most WPF projects. It allows you to use method, property or predicate.
public 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(nameof(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);
}
}

Capture command Parameter value in mvvm

I have two radio button.I just want to capture the selected radio button value in viewmodel.I have defined a method GetLOB() in which I want to capture the commandParameter value.
Here is my code
<RadioButton GroupName="Os" Content="Payroll" IsChecked="{Binding ObjEntrySheetManagerViewModel.CheckedProperty}" Command="LobType" CommandParameter="Payroll" Grid.Row="4" Grid.Column="0" Margin="25,15,0,0"/>
<RadioButton GroupName="Os" Content="Sales" Grid.Row="4" Grid.Column="1" Command="LobType" CommandParameter="Payroll" Margin="5,15,0,0"/>
private RelayCommand _LobType;
public ICommand LobType
{
get
{
if (_LobType == default(RelayCommand))
{
_LobType = new RelayCommand(GetLOB);
}
return _LobType;
}
}
private void GetLOB()
{
}
Capture parameter using lambda (assuming RelayCommand used by you have overloaded constructor which will take Action<object> as argument)
public ICommand LobType
{
get
{
if (_LobType == default(RelayCommand))
{
_LobType = new RelayCommand(param => GetLOB(param));
}
return _LobType;
}
}
private void GetLOB(object parameter)
{
}
Relay command sample from MSDN (in case you need):
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion
#region Constructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{ }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
[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);
}
#endregion
}

Simple MVVM binding issue

I have one textbox and one button. The Button Command should change the property which is binded to the TextBox.
But I don't see any visual changes after command execution.
I think it easy question related to wpf binding
Please help me with this issue
Source of app:
<UserControl.DataContext>
<local:SampleViewModel />
</UserControl.DataContext>
<Grid>
<StackPanel>
<TextBox Height="23" Width="120" Text="{Binding MyName}" />
<Button Content="Click" Command="{Binding ButtonCommand}" />
</StackPanel>
</Grid>
ViewModel:
Private _myName As String
Public Property MyName As String
Get
Return _myName
End Get
Set(value As String)
_myName = value
OnPropertyChanged("MyName")
End Set
End Property
Public _buttonCommand As DelegateCommand
Public ReadOnly Property ButtonCommand As DelegateCommand
Get
Return If(_buttonCommand IsNot Nothing, _buttonCommand,
New DelegateCommand(AddressOf Execute, AddressOf CanExecute))
End Get
End Property
Private Sub Execute()
MyName = "Executed"
End Sub
Private Function CanExecute() As Boolean
Return True
End Function
Public Event PropertyChanged As PropertyChangedEventHandler
Private Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Do the following:
1.
Class MainWindow
Implements INotifyPropertyChanged
2 . In Public Sub New() make sure you write Me.DataContext = Me to set the DataContext
Note: Ignore step 2 if you're using a ViewModel and setting it in XAML
3 . Modify the ProperyChanged like this:
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Only after implementing INotifyPropertyChanged correctly will the Binding correctly refresh the MyName property after the PropertyChanged event
Here is a code that works with your exact XAML (I took the DelegateCommand implementation from http://wpftutorial.net/DelegateCommand.html ) Sorry it's C#, i'm really not into VB :D
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public virtual bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public virtual void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
public class SampleViewModel : INotifyPropertyChanged
{
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public DelegateCommand _buttonCommand;
public DelegateCommand ButtonCommand
{
get
{
if (_buttonCommand == null)
{
_buttonCommand = new DelegateCommand(Execute);
}
return _buttonCommand;
}
}
public void Execute(object o)
{
MyName = "executed";
}
public string MyName { get { return _myName; } set { _myName = value; OnPropertyChanged("MyName"); } }
private string _myName;
}

Resources