Second example of UI: Focus management

Now, let’s assume we want to implement Copy&Paste in a Grid.

First alternative

Simply set the focus on the DataGrid in the Window constructor: a new row is not needed to enable commands like paste and new

public MainWindow()
{
    InitializeComponent();
    TheGrid.ItemsSource = numbers;
    TheGrid.Focus(); // numbers.Add(0) is not needed
}

Define the CanExecute events according to the expected conditions to enable the commands

private void CanCopy(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = numbers.Count > 0;
}

private void CanPaste(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = Clipboard.ContainsText(); // or true or whatever is your condition to paste;
}

A draft of Paste symmetric to your Copy method could be

your code here

Second/Suggested alternative

I want to highlight that – even without any TheGrid.Focus() in the code behind – just the following line in the XAML is working (of course with the above said CanExecute conditions for the ApplicationCommands).

<DataGrid x:Name="TheGrid" Focusable="True" 
FocusManager.FocusedElement="{Binding ElementName=TheGrid}">

The second alternative is my final suggested approach because it seems to me more xaml + mvvm oriented and it eliminates the need for calling Focus() from code behind so it can be even more instructive for you. In case of multiple DataGrids, with this approach you need to set IsFocusScope too and so you would have (replace Grid2 with GridN):

<DataGrid x:Name="TheGrid2" Focusable="True"  
              FocusManager.IsFocusScope="True"
              FocusManager.FocusedElement="{Binding ElementName=TheGrid2}" >
    <DataGrid.CommandBindings>
        <CommandBinding Command="{x:Static ApplicationCommands.Paste}" CanExecute="CanPaste2" Executed="Paste2"/>
        <CommandBinding Command="{x:Static ApplicationCommands.Copy}" CanExecute="CanCopy2" Executed="Copy2"/>
        <CommandBinding Command="{x:Static ApplicationCommands.New}" CanExecute="CanAddNew2" Executed="AddNew2"/>
    </DataGrid.CommandBindings>
        <DataGrid.ContextMenu>
            <ContextMenu >
            <MenuItem Command="{x:Static ApplicationCommands.Paste}" Header="Paste 2"/>
            <MenuItem Command="{x:Static ApplicationCommands.New}" Header="New row 2"/>
            <MenuItem Command="{x:Static ApplicationCommands.Copy}" Header="Copy 2"/>
        </ContextMenu>
    </DataGrid.ContextMenu>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Number2" Binding="{Binding}"/>
    </DataGrid.Columns>
    </DataGrid>

As a general suggestion, try to implement a basic MVVM that is a better design pattern than the code behind. Without MVVM you can proceed with the window constructor (remember that KeyGesture must be associated with one or more ModifierKeys)

RoutedCommand firstSettings = new RoutedCommand();
firstSettings.InputGestures.Add(new KeyGesture(Key.A, ModifierKeys.Alt));
CommandBindings.Add(new CommandBinding(firstSettings, AddNew1));
RoutedCommand secondSettings = new RoutedCommand();
secondSettings.InputGestures.Add(new KeyGesture(Key.B, ModifierKeys.Alt));
CommandBindings.Add(new CommandBinding(secondSettings, AddNew2));

Together with the corresponding InputGestureText (for example in Grid2)

<MenuItem Command="{x:Static ApplicationCommands.New}" 
	InputGestureText="Alt+B"  Header="New row 2"/>
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s