WPF: Implement ICommandSource Without Breaking IsEnabled - c#

I have created a TextBox that implements ICommandSource, for the most part I followed Microsoft's example using a Slider. This TextBox will execute the bound command upon pressing the "Enter" key. This portion of the behavior is working correctly, the issue I am having is that IsEnabled can no longer be set in XAML? I am not sure why this is, you can still set IsEnabled on native Microsoft classes like Button.
public class CommandTextBox : TextBox, ICommandSource
{
// The DependencyProperty for the Command.
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandTextBox), new PropertyMetadata(OnCommandChanged));
// The DependencyProperty for the CommandParameter.
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandTextBox));
// The DependencyProperty for the CommandTarget.
public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CommandTextBox));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public bool CommandResetsText { get; set; }
public IInputElement CommandTarget
{
get { return (IInputElement)GetValue(CommandTargetProperty); }
set { SetValue(CommandTargetProperty, value); }
}
// Command dependency property change callback.
private static void OnCommandChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
CommandTextBox ctb = (CommandTextBox)dp;
ctb.HookUpCommand((ICommand)e.OldValue, (ICommand)e.NewValue);
}
// Add a new command to the Command Property.
private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
{
// If oldCommand is not null, then we need to remove the handlers.
if (oldCommand != null)
RemoveCommand(oldCommand);
AddCommand(newCommand);
}
// Remove an old command from the Command Property.
private void RemoveCommand(ICommand command)
{
EventHandler handler = CanExecuteChanged;
command.CanExecuteChanged -= handler;
}
// Add the command.
private void AddCommand(ICommand command)
{
var handler = new EventHandler(CanExecuteChanged);
canExecuteChangedHandler = handler;
if (command != null)
command.CanExecuteChanged += canExecuteChangedHandler;
}
private void CanExecuteChanged(object sender, EventArgs e)
{
if (Command != null)
{
RoutedCommand command = Command as RoutedCommand;
// If a RoutedCommand.
if (command != null)
{
if (command.CanExecute(CommandParameter, CommandTarget))
this.IsEnabled = true;
else
this.IsEnabled = false;
}
// If a not RoutedCommand.
else
{
if (Command.CanExecute(CommandParameter))
this.IsEnabled = true;
else
this.IsEnabled = false;
}
}
}
// If Command is defined, pressing the enter key will invoke the command;
// Otherwise, the textbox will behave normally.
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Key == Key.Enter)
{
if (Command != null)
{
RoutedCommand command = Command as RoutedCommand;
if (command != null)
command.Execute(CommandParameter, CommandTarget);
else
Command.Execute(CommandParameter);
if (CommandResetsText)
this.Text = String.Empty;
}
}
}
private EventHandler canExecuteChangedHandler;
}
XAML
<Button Command="{Binding GenericCommand}" IsEnabled="False" /> // This is disabled(desired).
<CommandTextBox Command="{Binding GenericCommand}" IsEnabled="False" /> // This is enabled?
Any feedback would be appreciated.

First, you need to create a private property or a field that will be set if the command can execute:
private bool _canExecute;
Second, you need to override IsEnabledCore property:
protected override bool IsEnabledCore
{
get
{
return ( base.IsEnabledCore && _canExecute );
}
}
And finally, you just fixing CanExecuteChanged method by replacing IsEnabled with _canExecute and coercing IsEnabledCore after all:
private void CanExecuteChanged(object sender, EventArgs e)
{
if (Command != null)
{
RoutedCommand command = Command as RoutedCommand;
// If a RoutedCommand.
if (command != null)
{
_canExecute = command.CanExecute(CommandParameter, CommandTarget);
}
// If a not RoutedCommand.
else
{
_canExecute = Command.CanExecute(CommandParameter);
}
}
CoerceValue(UIElement.IsEnabledProperty);
}

Related

How to change Checkbox style and Background Color in Xamarin Forms

I am new at Xamarin forms and renderers, Can you please help me out in this,
Thank you in advance.
I have created a checkbox but I want to change its background color like in picture.
Now you can see in image default checkbox is there I want to change its background and style how can I do that?
<local:Checkbox x:Name="chkBrand" AutomationId="AutoIdCheckBox"
Content="{Binding LblBrand}"
Checked="{Binding Chk,Mode=TwoWay}">
</local:Checkbox>
Checkbox.cs
public class Checkbox : Xamarin.Forms.View
{
public static readonly BindableProperty CheckedProperty =
BindableProperty.Create("Checked",
typeof(bool),
typeof(Checkbox),
false, BindingMode.TwoWay, propertyChanged: OnCheckedPropertyChanged);
public static readonly BindableProperty ContentProperty =
BindableProperty.Create("Content",
typeof(string),
typeof(Checkbox),
"Content", BindingMode.OneWay);
public static readonly BindableProperty FontSizeProperty =
BindableProperty.Create("FontSize",
typeof(double),
typeof(Checkbox),
default(double), BindingMode.OneWay);
public bool Checked
{
get
{
return (bool)GetValue(CheckedProperty);
}
set
{
if (this.Checked != value)
{
SetValue(CheckedProperty, value);
if (CheckedChanged != null)
CheckedChanged.Invoke(this, new CheckedChangedEventArgs(value));
}
}
}
public string Content
{
get
{
return (string)GetValue(ContentProperty);
}
set
{
SetValue(ContentProperty, value);
}
}
public double FontSize
{
get
{
return (double)GetValue(FontSizeProperty);
}
set
{
SetValue(FontSizeProperty, value);
}
}
public event EventHandler<CheckedChangedEventArgs> CheckedChanged;
private static void OnCheckedPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
{
var checkBox = (Checkbox)bindable;
checkBox.Checked = newvalue != null ? (bool)newvalue : false;
}
}
and platform wise renderer are used. Adding UWP renderer for reference
public class CheckboxRenderer : ViewRenderer<Checkbox, CheckBox>
{
public new static void Init()
{
var temp = DateTime.Now;
}
protected override void OnElementChanged(ElementChangedEventArgs<Checkbox> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
if (Control == null)
{
var checkBox = new CheckBox();
checkBox.Checked += CheckBox_Checked;
checkBox.Unchecked += CheckBox_Unchecked;
SetNativeControl(checkBox);
}
if (e.NewElement != null)
{
Control.Content = e.NewElement.Content;
Control.IsChecked = e.NewElement.Checked;
Control.IsEnabled = e.NewElement.IsEnabled;
if (default(double) != e.NewElement.FontSize)
Control.FontSize = e.NewElement.FontSize;
}
}
private void CheckBox_Unchecked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
Element.Checked = Control.IsChecked.GetValueOrDefault();
}
private void CheckBox_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
Element.Checked = Control.IsChecked.GetValueOrDefault();
}
private void CheckBox_Content(object sender)
{
Element.Checked = Control.IsChecked.GetValueOrDefault();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
switch (e.PropertyName)
{
//case "IsVisible":
// Control.Hidden = Element.IsVisible;
// break;
case "IsEnabled":
Control.IsEnabled = Element.IsEnabled;
break;
case "Checked":
Control.IsChecked = Element.Checked;
break;
case "Content":
Control.Content = Element.Content;
break;
}
}
There are two ways to do this,
Use nuget package to show check box or
A simple way to change the style is to use the image control for checkbox.
Take two images as per your colour, one checked and other one is unchecked and do hide & show on click.

How to get CaretIndex value of TextBox control in the view model?

Since CaretIndex of TextBox control is not a DependencyProperty, how do I get the value of CaretIndex in the ViewModel?
You can you Interaction.Behaviors create your own behaviour and get the property you want from it.
For eg. this is a EventCommandConverterBehavior. Using it will return the property value which you specify from xaml, and if property name is not set. it will return Corresponding EventArgs
public class EventCommandConverterBehavior : Behavior<FrameworkElement>
{
private Delegate eventHandler;
private EventInfo oldEvent;
// Event
public string EventName { get { return (string)GetValue(EventNameProperty); } set { SetValue(EventNameProperty, value); } }
public static readonly DependencyProperty EventNameProperty = DependencyProperty.Register("EventName", typeof(string), typeof(EventCommandConverterBehavior), new PropertyMetadata(null, OnEventChanged));
// Command
public ICommand Command { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } }
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommandConverterBehavior), new PropertyMetadata(null));
public string PropertyName { get { return (string)GetValue(PropertyNameProperty); } set { SetValue(PropertyNameProperty, value); } }
public static readonly DependencyProperty PropertyNameProperty = DependencyProperty.Register("PropertyName", typeof(string), typeof(EventCommandConverterBehavior), new PropertyMetadata());
private static void OnEventChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
var behavior = (EventCommandConverterBehavior)dependencyObject;
if (behavior.AssociatedObject != null)
behavior.AttachHandler((string)args.NewValue);
}
protected override void OnAttached()
{
AttachHandler(this.EventName);
}
private void AttachHandler(string eventName)
{
// detach old event
if (this.oldEvent != null)
this.oldEvent.RemoveEventHandler(this.AssociatedObject, this.eventHandler);
// attach new event
if (string.IsNullOrEmpty(eventName))
{
return;
}
var eventInfo = this.AssociatedObject.GetType().GetEvent(eventName);
if (eventInfo != null)
{
var methodInfo = this.GetType()
.GetMethod("CommandExecuter", BindingFlags.Instance | BindingFlags.NonPublic);
this.eventHandler = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, methodInfo);
eventInfo.AddEventHandler(this.AssociatedObject, this.eventHandler);
this.oldEvent = eventInfo;
}
else
throw new ArgumentException(string.Format("Type {0} does not contain event {1} definition.",
this.AssociatedObject.GetType().Name, eventName));
}
private void CommandExecuter(object sender, EventArgs e)
{
object parameter = null != PropertyName ? GetPropValue(sender, PropertyName) : e;
if (this.Command != null)
{
if (this.Command.CanExecute(parameter))
this.Command.Execute(parameter);
}
}
public static object GetPropValue(object src, string propName)
{
var propertyInfo = src.GetType().GetProperty(propName);
return propertyInfo != null ? propertyInfo.GetValue(src, null) : null;
}
}
In Xaml you have to write
<TextBox Name="TextBox1" Text="SomeText" Height="20" Width="60">
<i:Interaction.Behaviors >
<wpfPractice:EventCommandConverterBehavior Command="{Binding PropertyValueCommand}" EventName="SelectionChanged" PropertyName="CaretIndex" />
</i:Interaction.Behaviors>
</TextBox>
Where PropertyValueCommand shold be a command in DataContext(i.e. ViewModel.
let me know if it works.

Relaycommand ICommand.CanExecute not firing

i have the following problem:
I have a relaycommand with a execute an a canexecute method, but everytime i call raisecanexecutechanged(); it calls raisecanexecutechanged in relaycommand, sets a new delegate for it and then returns back to the view model.
The same setup works in another viewmodel. I checked like 1000 times what's different but i don't find anything.
I would really appreciate if you could help me.
public RelayCommand UpdateAMSCommand { get; private set; }
public AMSSettingsViewModel(IEventAggregator eventAggregator)
{
UpdateAMSCommand = new RelayCommand(OnUpdateAMS, CanUpdateAms);
CustomAMSOffices.ListChanged += listChanged;
CustomAMSContacts.ListChanged += listChanged;
}
private void listChanged(object sender, ListChangedEventArgs e)
{
if (sender != null)
{
if (sender is BindingList<CustomAMSOffice>)
{
BindingList<CustomAMSOffice> temp = (BindingList<CustomAMSOffice>)sender;
if (temp.Count > _amsOfficesItemsCounter)
{
_amsOfficesItemsCounter = temp.Count;
for (int i = 0; i < temp.Count; i++)
{
temp[i].ErrorsChanged += RaiseCanExecuteChanged;
}
}
}
else if (sender is BindingList<CustomAMSContact>)
{
BindingList<CustomAMSContact> temp = (BindingList<CustomAMSContact>)sender;
if (temp.Count > _amsContactsItemsCounter)
{
_amsContactsItemsCounter = temp.Count;
for (int i = 0; i < temp.Count; i++)
{
temp[i].ErrorsChanged += RaiseCanExecuteChanged;
}
}
}
}
UpdateAMSCommand.RaiseCanExecuteChanged();
}
private void RaiseCanExecuteChanged(object sender, DataErrorsChangedEventArgs e)
{
UpdateAMSCommand.RaiseCanExecuteChanged();
}
private bool CanUpdateAms()
{
foreach (var cao in CustomAMSOffices)
{
if (!cao.Check() || cao.HasErrors)
{
return false;
}
}
foreach (var cac in CustomAMSContacts)
{
if (!cac.Check() || cac.HasErrors)
{
return false;
}
}
return true;
}
Edit:
the relaycommand i use: https://github.com/briannoyes/WPFMVVM-StarterCode/blob/master/ZzaDashboard/ZzaDashboard/RelayCommand.cs
Ok, I'm just going to copy paste some code that I have in use, so that you should be able to pop these into your project and use.
First off, the RelayCommand() class. I lifted this code from this msdn page:
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
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
}
Now our ModelView.cs class needs to inherit from INotifyPropertyChangedand will have our RaisePropertyChanged(). Now I usually make just make this a it's own file and have all my ModelViews inherit from it so the code is a little cleaner, but you can do as you please.
Here's how I have it setup though:
BaseViewModel.cs:
public class BaseViewModel : INotifyPropertyChanged
{
internal void RaisePropertyChanged(string prop)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
public event PropertyChangedEventHandler PropertyChanged;
// Any other code we want all model views to have
}
Now for our MainViewModel.cs we will just inherit from BaseViewModel, add our event handlers in, and run it!
Example: ServerViewModel.cs
public class ServerViewModel : BaseViewModel
{
public RelayCommand BroadcastMessageCommand { get; set; }
private string _broadcastmessage;
public string broadcastmessage
{
get { return _broadcastmessage; }
set { _broadcastmessage = value; RaisePropertyChanged("broadcastmessage"); }
}
Server server;
public ServerViewModel()
{
server = new Server();
server.run();
BroadcastMessageCommand = new RelayCommand(BroadcastMessage, CanBroadcast);
}
private bool CanBroadcast(object param)
{
if (string.IsNullOrWhiteSpace(broadcastmessage))
return false;
if (!server.running)
return false;
return true;
}
public void BroadcastMessage(object param)
{
server.BroadcastMessage(broadcastmessage);
broadcastmessage = "";
RaisePropertyChanged("broadcastmessage");
}
}
Now anything in our MainView.xaml that is bound with Command="{Binding broadcastmessage}" will update appropriately. In my case I have this bound to a button and the button will be disabled if there message is empty, or if we are not connected to the server.
Hopefully that's enough code example to get you headed in the right direction! Let me know if you have any questions on it.
Let's try simplifying the code as much as we can until we get this working properly, and then we will slowly add code back until we find the code(s) that are causing trouble.
So let's reduce this to it's barebones and see if we have any success. Try this code:
public RelayCommand UpdateAMSCommand { get; private set; }
public AMSSettingsViewModel(IEventAggregator eventAggregator)
{
UpdateAMSCommand = new RelayCommand(OnUpdateAMS, CanUpdateAms);
CustomAMSOffices.ListChanged += listChanged;
CustomAMSContacts.ListChanged += listChanged;
}
private void listChanged(object sender, ListChangedEventArgs e)
{
UpdateAMSCommand.RaiseCanExecuteChanged();
}
private void RaiseCanExecuteChanged(object sender, DataErrorsChangedEventArgs e)
{
UpdateAMSCommand.RaiseCanExecuteChanged();
}
// This will simply flip from true to false every time it is called.
private bool _canupdate = false;
private bool CanUpdateAms()
{
_canupdate = !_canupdate;
return _canupdate;
}
Edit: I don't know why it doesn't work.

WPF disable command for a while it running

I need to disable button for a while it running. I have this code:
RelayCommand.cs This is my command class.
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("execute");
}
_execute = execute;
_canExecute = canExecute;
}
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);
}
}
MainWindowViewModel.cs This is my command for binding.
private RelayCommand _getTextCommand;
public ICommand GetTextCommand
{
get
{
if (_getTextCommand == null)
{
_getTextCommand = new RelayCommand(
param => this.GetText(param),
param => true
);
}
return _getTextCommand;
}
}
MainWindow.xaml This is XAML code where i bind my command.
<Button x:Name="getTextButton" Command="{Binding GetTextCommand}" CommandParameter="{Binding ElementName=textTypeSelector, Path=SelectedIndex}"/>
This is the code i am launching in command:
public async void GetText(object o)
{
await Task.Factory.StartNew(() =>
{
// code
});
}
Try this: add a boolean property in view model and implement INotifyPropertyChanged in view model
private bool isEnable = true;
public bool IsEnable
{
get { return isEnable; }
set
{
isEnable = value;
NotifyPropertyChanged();
}
}
public async void GetText(object o)
{
await Task.Factory.StartNew(() =>
{
IsEnable = false;
});
IsEnable = true;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Bind it to button IsEnable property
<Button x:Name="abc"
Command="{Binding GetTextCommand}"
IsEnabled="{Binding IsEnable}" />
Set IsEnable whereever you want.
Add a boolean to your ViewModel to indicate that the command is executing and set the boolean in your GetText() method.
private bool _isRunning = false;
public async void GetText(object o)
{
await Task.Factory.StartNew(() =>
{
_isRunning = true;
CommandManager.InvalidateRequerySuggested();
// code
_isRunning = false;
CommandManager.InvalidateRequerySuggested();
});
}
public bool CanGetText(object o){
return ! _isRunning;
}
Then change your RelayCommand to the following
_getTextCommand = new RelayCommand(this.GetText,CanGetText);
The problem is that you are passing true for the CanExecute delegate. Pass it a method that will execute every time it needs evaluation, and within that method you can test to see whether the Command should be executable or otherwise.
Here is an implementation that I'm using. It doesn't need an additional property in the ViewModel.
public sealed class AsyncDelegateCommand : ICommand
{
private readonly Func<bool> _canExecute;
private readonly Func<Task> _executeAsync;
private Task _currentExecution;
public AsyncDelegateCommand(Func<Task> executeAsync)
: this(executeAsync, null)
{
}
public AsyncDelegateCommand(Func<Task> executeAsync, Func<bool> canExecute)
{
if (executeAsync == null) throw new ArgumentNullException("executeAsync");
_executeAsync = executeAsync;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
if (_currentExecution != null && !_currentExecution.IsCompleted)
{
return false;
}
return _canExecute == null || _canExecute();
}
public async void Execute(object parameter)
{
try
{
_currentExecution = _executeAsync();
await _currentExecution;
}
finally
{
_currentExecution = null;
CommandManager.InvalidateRequerySuggested();
}
}
}

how can i focus textbox in xaml with keybinding?

How can I set focus on a TextBox when F3 key pressed.
In other words, do some thing like bellow:
private void Window_PreviewKeyDown(object sender, KeyEventArgs )
{
switch (e.Key)
{
case Key.F3:
myTextBox1.Focus();
break;
case Key.F4:
myTextBox2.Focus();
break;
default:
break;
}
}
note:I want to do it in xaml.
You could do this by created an attached property that takes a shortcut key then create an input binding on the window hosting that control.. it's a bit of a complex class but very easy to use.
start by adding a new class to your project below.
public class TextBoxHelper : DependencyObject
{
public class MvvmCommand : DependencyObject, ICommand
{
readonly Action<object> _execute;
readonly Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged;
public MvvmCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
if (execute == null) throw new ArgumentNullException("command");
_canExecute = canExecute == null ? parmeter => MvvmCommand.AlwaysCanExecute() : canExecute;
_execute = execute;
}
public object Tag
{
get { return (object)GetValue(TagProperty); }
set { SetValue(TagProperty, value); }
}
public static readonly DependencyProperty TagProperty = DependencyProperty.Register("Tag", typeof(object), typeof(MvvmCommand), new PropertyMetadata(null));
static bool AlwaysCanExecute()
{
return true;
}
public void EvaluateCanExecute()
{
EventHandler temp = CanExecuteChanged;
if (temp != null)
temp(this, EventArgs.Empty);
}
public virtual void Execute(object parameter)
{
_execute(parameter == null ? this : parameter);
}
public virtual bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
}
public static Key GetFocusKey(DependencyObject obj)
{
return (Key)obj.GetValue(FocusKeyProperty);
}
public static void SetFocusKey(DependencyObject obj, Key value)
{
obj.SetValue(FocusKeyProperty, value);
}
public static readonly DependencyProperty FocusKeyProperty =
DependencyProperty.RegisterAttached("FocusKey", typeof(Key), typeof(TextBoxHelper), new PropertyMetadata(Key.None, new PropertyChangedCallback((s, e) =>
{
UIElement targetElement = s as UIElement;
if (targetElement != null)
{
MvvmCommand command = new MvvmCommand(parameter => TextBoxHelper.FocusCommand(parameter))
{
Tag = targetElement,
};
InputGesture inputg = new KeyGesture((Key)e.NewValue);
(Window.GetWindow(targetElement)).InputBindings.Add(new InputBinding(command, inputg));
}
})));
public static void FocusCommand(object parameter)
{
MvvmCommand targetCommand = parameter as MvvmCommand;
if (targetCommand != null)
{
UIElement targetElement = targetCommand.Tag as UIElement;
if (targetElement != null)
{
targetElement.Focus();
}
}
}
}
now in XAML all you need to do to set your focus keys is assign that FocusKey property, an example below has 2 textboxes, one gets focus when F1 is pressed, the other when F7 is pressed.
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication5"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="131" Width="460">
<Grid Margin="10">
<TextBox Margin="0,0,0,60" local:TextBoxHelper.FocusKey="F1" />
<TextBox Margin="0,35,0,0" local:TextBoxHelper.FocusKey="F7" />
</Grid>
</Window>

Categories