How to pass a UserControl with CommandParameter? - c#

I have using a DelegateCommand and i want to pass the UserControl with Command.
#region OpenViewCommand
private DelegateCommand<UserControl> _openViewCommand;
public ICommand OpenViewCommand
{
get
{
if (_openViewCommand == null)
_openViewCommand = new DelegateCommand<UserControl>(new Action<UserControl>(OpenView));
return _openViewCommand;
}
}
public void OpenView(UserControl ViewName)
{
UserControl ctrl = (UserControl)ViewName;
JIMS.Controls.Message.Show(ViewName.ToString());
}
#endregion
Command in XAML
<Button Name="btnStockGroups" Command="{Binding OpenViewCommand}" CommandParameter="JIMS.View.Stock.StockGroups">stock group</Button>

If you give your UserControl an x:Name (e.g. "MyView"), you should be able to do something like this:
<Button Name="btnStockGroups"
Command="{Binding OpenViewCommand}"
CommandParameter="{Binding ElementName=MyView}">

Related

Pass three parameters to Prism DelegateCommand to use the same command on different button commands [MVVM mode]

I have the following DelegateCommand, created with the Prism library.
public class AddressModel : INotifyPropertyChanged
{
public ICommand MyButtonClickCommand
{
get { return new DelegateCommand<object>(FuncToCall); }
}
public void FuncToCall(object context)
{
//this is called when the button is clicked
Method1("string1", integer_number1);
}
}
I have already bonded MyButtonClickCommand to a button in XAML file.
<Button Content="Click me"
Command="{Binding MyButtonClickCommand}"/>
But I would like to use the same MyButtonClickCommand for 2 more buttons instead of creating two additional DelegateCommands MyButtonClickCommand1 & MyButtonClickCommand2.
So what I want is to add string1 and integer_number1 as parameters and call the same ICommand on different buttons like below
<Button Content="Click me"
Command="{Binding MyButtonClickCommand("string1", integer_number1)}"/>
<Button Content="Click me 2"
Command="{Binding MyButtonClickCommand("string2", integer_number2)}"/>
<Button Content="Click me 3"
Command="{Binding MyButtonClickCommand("string3", integer_number3)}"/>
You can pass an instance of any class that could be declared in XAML
public class MyCommandParameter
{
public int MyInt { get; set; }
public string MyString { get; set; }
}
to the CommandParameter property of a Button:
<Button Content="Click me" Command="{Binding ...}">
<Button.CommandParameter>
<local:MyCommandParameter MyInt="2" MyString="Hello"/>
</Button.CommandParameter>
</Button>
The MyCommandParameter instance is passed to the Execute handler method's argument:
public void FuncToCall(object parameter)
{
var param = (MyCommandParameter)parameter;
// do something with param.MyInt and param.MyString
}
Use the CommandParameter property:
<Button Content="Click me 2"
Command="{Binding MyButtonClickCommand}"
CommandParameter="2" />
You could then cast the context parameter to whatever the value of the command parameter is:
public void FuncToCall(object context)
{
string parameter = context as string;
if (int.TryParse(parameter, out int number))
{
//---
}
}

Binding Exceed IntegerUpDown value to a CommandParameter

I am using Exceed IntegerUpDown control in my .xaml file. I want to bind IntegerUpDown value as a CommandParameter of a button.
I do not have any code behind files and this is a custom control xaml file. So i want to achieve this by only using xaml systax.
<DockPanel>
<xctk:IntegerUpDown x:Name="ExtraExpressionValue" Increment="1" FormatString="N0" AllowSpin="True" Width="70" Watermark="Numeric" AllowTextInput="False" Minimum="0" Value="999"/>
<Button Style="{StaticResource ContextMenuButton}" Margin="5,0,0,0" Content="Add" Command="{Binding SetExtaExpressionValueCommand}" CommandParameter="{Binding ElementName=ExtraExpressionValue,Path=Value}"/>
</DockPanel>
Above is my xaml code. this return 0 to command method.
My command class is as follows,
public class DesignItemCommands
{
private ICommand setExtaExpressionValueCommand;
public ICommand SetExtaExpressionValueCommand => setExtaExpressionValueCommand ?? (setExtaExpressionValueCommand = new CommandHandler(SetExtaExpressionValue, canExecute));
private bool canExecute;
public DesignItemCommands()
{
canExecute = true;
}
private void SetExtaExpressionValue(object parameter)
{
//I need parameter here..
}
}
Couldn't find a way on the requirement. Just posting here to help someone later on this issue.
I used a ViewModel Variable to bind IntegerUpDown control value.
<DockPanel>
<xctk:IntegerUpDown Increment="1" Value="{Binding ExtraExpressionValue}"/>
<Button Content="Add" Command="{Binding SetExtaExpressionValueCommand}"/>
</DockPanel>
My ViewModel is as follows,
public class DesignItemCommands
{
private ICommand setExtaExpressionValueCommand;
public ICommand SetExtaExpressionValueCommand => setExtaExpressionValueCommand ?? (setExtaExpressionValueCommand = new CommandHandler(SetExtaExpressionValue, canExecute));
private bool canExecute;
public int ExtraExpressionValue { get; set; }
public DesignItemCommands()
{
canExecute = true;
ExtraExpressionValue = 1;
}
private void SetExtaExpressionValue(object parameter)
{
//I can use value here using variable ExtraExpressionValue
}
}
Hope this helps someone later.

How to pass a command in XAML?

I have a Page with a ViewModel as a BindingContext:
public Page()
{
InitializeComponent();
this.BindingContext = new ViewModel();
}
ViewModel has a command:
public class ViewModel : INotifyPropertyChanged
{
...
public ICommand SomeCommand { get; set; }
public ViewModel()
{
SomeCommand = new Command((object data) => {});
}
...
}
In my Page.xaml I use my custom View component which serves the only to be displayed and has an ability to be clicked:
<local:CircleView
Radius="20"
InnerText="Click me"
InnerTextSize="15"
TapCommand="{Binding SomeCommand}"
/>
In my CircleView.xaml.cs
...
public ICommand TapCommand { get; set; }
...
In my CircleView.xaml:
...
<TapGestureRecognizer
Command="{Binding Path=TapCommand, Source={x:Reference Name=CircleView}}"
CommandParameter="{Binding Path=InnerText, Source={x:Reference Name=CircleView}}"
/>
...
When I run a program I get an error "No property, bindable property, or event found for TapCommand, or mismatching...". How can I pass a command in XAML?
You should add your TapCommand as dependency property to your user control. Add this to your CircleView.xaml.cs and remove the previously defined TapCommand.
See also: dependency-properties-overview
//making is a bindab
public static readonly DependencyProperty TapCommandProperty =
DependencyProperty.Register("TapCommand", typeof(ICommand), typeof(CircleView)
/* possible more options here, see metadata overrides in msdn article*/);
public ICommand TapCommand
{
get { return (ICommand)GetValue(TapCommandProperty); }
set { SetValue(TapCommandProperty, value); }
}
Then, I am not sure, but since you are using the TapCommand in your TapGestureRecognizer I think you'll need to implement INotificationChanged on your CircleView as well.
You need to pass a reference to the ViewModel to the CircleView by adding a bindable property to the CircleView:
public static BindableProperty ParentBindingContextProperty =
BindableProperty.Create(nameof(ParentBindingContext), typeof(object),
typeof(CircleView), null);
public object ParentBindingContext
{
get { return GetValue(ParentBindingContextProperty); }
set { SetValue(ParentBindingContextProperty, value); }
}
You can then bind that in your xaml (note the x:Name must match the x:Reference):
<ContentView ... x:Name="Home" ... >
...
<local:CircleView ParentBindingContext="{Binding Source={x:Reference Home}, Path=BindingContext}"/>
And finally, bind your tap gesture to the command in your "parent" view model in your xaml in your CircleView:
<TapGestureRecognizer BindingContext="{Binding Source={x:Reference CircleView}, Path=ParentBindingContext}" Command="{Binding Path=TapCommand}" CommandParameter="{Binding Path=InnerText, Source={x:Reference Name=CircleView}}" />
You won't need the TapCommand in your CircleView.

Cannot hit the getter of Property

I am trying to use AvalonDock in Prism. All works fine except MenuItem "Tools->Properties". The MenuItem "File->New" works fine - new window is created and I can dock wherever I want.
This code works okay in simple MVVM application(without Prism) – “MenuItem” is fired always.
What I have:
<UserControl x:Class="ModuleCAvalonDock.ViewC">
<Menu>
<MenuItem Header="File">
<MenuItem Header="New" Command="{Binding NewCommand}"/>
<MenuItem Header="Open" Command="{Binding OpenCommand}"/>
<Separator/>
<MenuItem Header="Save" Command="{Binding ActiveDocument.SaveCommand}"/>
<MenuItem Header="Save As..." Command="{Binding ActiveDocument.SaveAsCommand}"/>
<Separator/>
<MenuItem Header="Close" Command="{Binding ActiveDocument.CloseCommand}"/>
</MenuItem>
<MenuItem Header="Tools">
<MenuItem Header="Properties" IsChecked="{Binding FileStats.IsVisible, Mode=TwoWay}" IsCheckable="True"/>
</MenuItem>
<MenuItem Header="Layout">
<MenuItem Header="Load" Command="{Binding LoadLayoutCommand, ElementName=mainWindow}"/>
<MenuItem Header="Save" Command="{Binding SaveLayoutCommand, ElementName=mainWindow}"/>
<MenuItem Header="Dump to Console" Click="OnDumpToConsole"/>
</MenuItem>
</Menu>
</UserControl>
How I am binding:
public ViewC(IViewModel viewModel)
{
InitializeComponent();
this.DataContext = Workspace.This;
}
and ViewModel:
public class Workspace:ViewModelBase
{
FileStatsViewModel _fileStats = null;
public FileStatsViewModel FileStats
{
get
{
if (_fileStats == null)
_fileStats = new FileStatsViewModel();
return _fileStats;
}
}
RelayCommand _newCommand = null;
public ICommand NewCommand
{
get
{
if (_newCommand == null)
{
_newCommand = new RelayCommand((p) => OnNew(p), (p) => CanNew(p));
}
return _newCommand;
}
}
private bool CanNew(object parameter)
{
return true;
}
private void OnNew(object parameter)
{
_files.Add(new FileViewModel());
ActiveDocument = _files.Last();
}
protected Workspace()
{
}
static Workspace _this = new Workspace();
public static Workspace This
{
get { return _this; }
}
}
FileStatsViewModel:
public class FileStatsViewModel : ToolViewModel { }
public class ToolViewModel
{
private bool _isVisible = true;
public bool IsVisible
{
get { return _isVisible; }
set
{
if (_isVisible != value)
{
_isVisible = value;
RaisePropertyChanged("IsVisible");
}
}
}
}
However, It does not work in Prism. I’ve tried setting some break point to check if the property is fired and FileStats property is firing in simple MVVM application, but FileStats property is not firing in Prism application!
The code where I initialize my View:
public class ModuleCModule: ModuleBase
{
public ModuleCModule(IUnityContainer container, IRegionManager regionManager)
: base(container, regionManager) { }
protected override void InitializeModule()
{
RegionManager.RegisterViewWithRegion(RegionNames.ContentRegion, typeof(ViewC));
}
protected override void RegisterTypes()
{
Container.RegisterTypeForNavigation<ViewC>();
}
}
It is really interesting that I can fire my command <MenuItem Header="New" Command="{Binding NewCommand}"/>. However, I cannot fire property FileStats at viewModel Workspace.
How to fire my property? What am I doing wrong?
Prism has no impact on the WPF binding system, so this is an issue with how you are creating the binding to the DataContext of the view. How are you assigning the ViewModel to the DataContext of your View? Check your output window for binding errors. Chances are your DataContext is not being set.
If you are using the ViewModelLocator, then make sure you are following the proper naming conventions:
http://brianlagunas.com/getting-started-prisms-new-viewmodellocator/
EDIT: I ran your app as is, and was able to hit the setter on your FileStats.IsVisible property. If you are placing a breakpoint on the getter of FileStats, well that won't fire when you click on the menu item, because you are bound to a property of FileStats, not FileStats which is read-only anyways. By the way, you know Prism 6.1 is out (you're using v4). Also, you should try using NuGet instead of hard references.

Create Key binding in WPF

I need to create input binding for Window.
public class MainWindow : Window
{
public MainWindow()
{
SomeCommand = ??? () => OnAction();
}
public ICommand SomeCommand { get; private set; }
public void OnAction()
{
SomeControl.DoSomething();
}
}
<Window>
<Window.InputBindings>
<KeyBinding Command="{Binding SomeCommand}" Key="F5"></KeyBinding>
</Window.InputBindings>
</Window>
If I init SomeCommand with some CustomCommand : ICommand it doesn't fire. SomeCommand property getter is never called.
For your case best way used MVVM pattern
XAML:
<Window>
<Window.InputBindings>
<KeyBinding Command="{Binding SomeCommand}" Key="F5"/>
</Window.InputBindings>
</Window>
Code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
In your view-model:
public class MyViewModel
{
private ICommand someCommand;
public ICommand SomeCommand
{
get
{
return someCommand
?? (someCommand = new ActionCommand(() =>
{
MessageBox.Show("SomeCommand");
}));
}
}
}
Then you'll need an implementation of ICommand.
This simple helpful class.
public class ActionCommand : ICommand
{
private readonly Action _action;
public ActionCommand(Action action)
{
_action = action;
}
public void Execute(object parameter)
{
_action();
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
}
For modifiers (key combinations):
<KeyBinding Command="{Binding SaveCommand}" Modifiers="Control" Key="S"/>
It might be too late but here is the simplest and shortest solution.
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.S)
{
// Call your method here
}
}
<Window x:Class="Test.MainWindow" KeyDown="Window_KeyDown" >
You will have to create your own Command implementing ICommand interface and initialize SomeCommand with the instance of that Command.
Now you have to set the DataContext of Window to self in order to make the Command Binding work:
public MainWindow()
{
InitializeComponents();
DataContext = this;
SomeCommand = MyCommand() => OnAction();
}
OR you will have to update your Binding as
<Window>
<Window.InputBindings>
<KeyBinding Command="{Binding SomeCommand, RelativeSource={RelativeSource Self}}" Key="F5"></KeyBinding>
</Window.InputBindings>
</Window>
This is how I solved this problem in my project:
<Window x:Class="MyNamespace.MyView"
(...)
xmlns:local="clr-namespace:MyNameSpace"
(...)
<Grid>
<Grid.InputBindings>
<KeyBinding Key="R" Command="{Binding ReportCommand,
RelativeSource={RelativeSource AncestorType=local:MyView}}" />
(...)
ReportCommand is an ICommand in MyView, not in the ViewModel.

Categories

Resources