Muszę zaimplementować niestandardową kopię + wyciąć + wkleić dane (nie tekst lub CSV), które mają być kopiowane między siatkami w aplikacji WPF. Używanie standardowych poleceń ApplicationCommands i definiowanie CommandBinding działa naprawdę dobrze, ale tylko wtedy, gdy DataGrid zawiera co najmniej 1 wiersz danych i kiedy jest wybrany. Gdy nie ma żadnych wierszy lub fokus nie znajduje się na żadnym z nich, wszystkie polecenia są wyłączone.Zaimplementuj niestandardowe kopiuj i wklej w WPF DataGrid, które działa, gdy nie ma w nim wierszy.
Aby rozwiązać problem, próbowałem wywołać CommandManager.InvalidateRequerySuggested() i ustawić Focusable = true i/lub FocusManager.IsFocusScope = true na DataGrid, ale wydaje się, że wewnętrznie DataGrid jako całość nie jest "zainteresowany" obsługą Kopiuj/Wklej operacje, tylko jego wiersze ponawiają zapytania do poleceń CanExecute i wywołują odpowiednio Execute. Ignoruje także KeyBindings.
Jak sprawić, aby uchwyt DataGrid wymagał obsługi poleceń aplikacji?
Proszę znaleźć przykład, na którym testowałem poniższego problemu:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DataGrid x:Name="TheGrid">
<DataGrid.Columns>
<DataGridTextColumn Header="Number" Binding="{Binding}"/>
</DataGrid.Columns>
<DataGrid.InputBindings>
<KeyBinding Key="A" Command="{x:Static ApplicationCommands.New}"/>
</DataGrid.InputBindings>
<DataGrid.CommandBindings>
<CommandBinding Command="{x:Static ApplicationCommands.Paste}" CanExecute="CanPaste" Executed="Paste"/>
<CommandBinding Command="{x:Static ApplicationCommands.Copy}" CanExecute="CanCopy" Executed="Copy"/>
<CommandBinding Command="{x:Static ApplicationCommands.New}" CanExecute="CanAddNew" Executed="AddNew"/>
</DataGrid.CommandBindings>
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Command="{x:Static ApplicationCommands.Copy}" Header="Copy"/>
<MenuItem Command="{x:Static ApplicationCommands.Paste}" Header="Paste"/>
<MenuItem Command="{x:Static ApplicationCommands.New}" Header="New row"/>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
</Window>
i kodeksem tyle:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
TheGrid.ItemsSource = numbers;
// Following line enables commands when row is selected
numbers.Add(0);
}
private void Copy(object sender, ExecutedRoutedEventArgs e)
{
Clipboard.SetData(DataFormats.Text, string.Join(",", numbers));
}
private void CanCopy(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = numbers.Count > 0;
}
private void CanPaste(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = numbers.Count > 0;
e.Handled = true;
}
private void Paste(object sender, ExecutedRoutedEventArgs e)
{
Close();
}
private void CanAddNew(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
private void AddNew(object sender, ExecutedRoutedEventArgs e)
{
numbers.Add(numbers.Count);
}
private readonly ICollection<int> numbers = new ObservableCollection<int>();
}
}
Edycja
Kod jedynym rozwiązaniem przez ajjappan Subramanian jest najbardziej pasuje do aplikacji, w której będzie używany. Ostatecznie, ponieważ już dziedziczyłem siatkę, ponieważ ma ona niestandardowego policjanta Format pasta y + do pracy, dodałem trochę kodu, który zapewnia, że koncentruje się w obrębie siatki w 3 przypadkach: Menu
- Kontekst jest pokazany
- użytkownik kliknie na (pusty) obszaru siatki, kiedy to wizualizacje potomnych nie koncentrują się na tym, co się stało:
- (Nasz przypadek specyficzny dla aplikacji) Użytkownik klika na siatkę nawigacji TreeView, która następnie ustawia ostrość na siatkę, aby skróty działały od razu.
odpowiedni kod:
public class MyDataGrid: DataGrid
{
protected override void OnContextMenuOpening(ContextMenuEventArgs e)
{
base.OnContextMenuOpening(e);
Focus();
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
base.OnMouseUp(e);
if(e.ChangedButton == MouseButton.Left && !IsKeyboardFocusWithin)
{
Focus();
}
}
}
myślę, że może to być spowodowane linii -> ** e.CanExecute = numbers.Count> 0; ** spróbuj zmienić linię w funkcji CanPaste do ** e.CanExecute = true; ** –
Przepraszam, ale nie włączono żadnej akcji bez skupienia się na wierszu, w tym ApplicationCommands.New i ma on ustawioną wartość e.CanExecute zawsze na true. – too