Нажмите Событие, не запущенное в WPF Datagrid в невыбранной строке - PullRequest
6 голосов
/ 08 декабря 2011

У меня есть DataGrid (WPF 4), подобный этому:

<DataGrid   Margin="0,0,0,5" VerticalAlignment="Top" Height="192" 
                            BorderBrush="#aaa" Background="White" 
                            HorizontalAlignment="Left" 
                            ItemsSource="{Binding Namen, Mode=OneWay}" 
                            ScrollViewer.VerticalScrollBarVisibility="Visible"
                            AutoGenerateColumns="False" 
                            ColumnHeaderHeight="24" 
                            SelectionChanged="DataGridAuslaendischeAlteNamen_SelectionChanged">
                    <DataGrid.Columns>
                        <DataGridTextColumn Width="*" Header="Namenseintrag" Binding="{Binding DisplayName, Mode=OneWay}" />
                        <DataGridTextColumn Width="75" Header="gültig von" Binding="{Binding GueltigAb, StringFormat=d, Mode=OneWay}" />
                        <DataGridTextColumn Width="75" Header="gültig bis" Binding="{Binding GueltigBis, StringFormat=d., Mode=OneWay}" />
                        <DataGridTemplateColumn Width="20" IsReadOnly="True">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Button Style="{DynamicResource CaratRemoveButton}" 
                                            Click="Button_Click" CommandParameter="{Binding}" 
                                            PreviewMouseDown="Button_PreviewMouseDown" 
                                            />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                </DataGrid.Columns>
                </DataGrid>

Проблема, с которой я сталкиваюсь, заключается в том, что кнопка DataGridTemplateColumn не запускает событие click, если ее строка невыбран.Поэтому мне нужно дважды нажать кнопку, один раз, чтобы выбрать ее строку, а затем вызвать событие щелчка.Я читал о похожих проблемах с флажками-столбцами, но там было предложение использовать столбец шаблона.Я протестировал использование PreviewMouseDown-Event кнопки, которая работает, но это не то, что мне нужно, поскольку кнопка не соответствует своему обычному поведению щелчка мыши.

Что мне здесь не хватает?Как я могу получить это событие, щелкнув один раз, независимо от того, была выбрана строка или нет?

Ответы [ 6 ]

8 голосов
/ 08 декабря 2011

в принципе, у вас нет решения, кроме как использовать TemplateColumn и управлять каждым mouseEvent самостоятельно.

Объяснение:

click = mouseDown + MouseUp, вправо. поэтому ваша кнопка должна иметь возможность получить mouseDown + событие MouseUp.

НО ...

по умолчанию, DataGrid wpf имеет строки, обрабатывающие событие MouseDown, чтобы выбрать тот, который вы делаете на mouseDown (для подтверждения: mouseDown в ячейке и удерживая кнопку мыши нажатой, вы увидите что строка выбрана ДО вы отпустите кнопку).

Таким образом, MouseDownEvent обрабатывается до того, как достигает кнопки, что не позволяет вам использовать событие Click для кнопки

Microsoft в своем документе сообщает нам, что в таких случаях мы должны обращаться к событию Preview , но это не может применяться к событию click, поскольку вы не можете получить previewClickEvent.

Таким образом, единственное решение, которое я вижу для вас, - это слушать как PreviewMouseDown и PreviewMouseUp на вашей кнопке, так и имитировать нажатие от них самостоятельно

что-то вроде этого:

Button myButton = new Button();
bool mouseLeftButtonDownOnMyButton;
myButton.PreviewMouseLeftButtonDown += (s, e) => { mouseLeftButtonDownOnMyButton = true; };
myButton.PreviewMouseLeftButtonUp += (s, e) => {
    if (mouseLeftButtonDownOnMyButton)
        myButton.RaiseEvent( new RoutedEventArgs(Button.ClickEvent,myButton));
        mouseLeftButtonDownOnMyButton = false;
    };
myButton.Click += myButtonCLickHandler;

(конечно, вам нужно перевести это в шаблоне xaml)

NB: это не завершено, вы должны также позаботиться о случаях, когда пользователь нажимает кнопку мыши на кнопке, но перемещает мышь из кнопки перед выполнением операции мыши (в случае, если вы должен сбросить флаг mouseLeftButtonDownOnMyButton). Вероятно, лучшим способом было бы сбросить флаг в обычном mouseUpEvent (например, на уровне окна) вместо кнопки.

Редактировать: приведенный выше код позволяет вам также управлять событием Click и иметь только один код как для реальных, так и для имитируемых событий click (отсюда и использование метода RaiseEvent), но если вы не В этом нет необходимости, вы можете, конечно, напрямую поместить свой код в раздел PreviewMouseUp.

0 голосов
/ 02 октября 2017

Слишком поздно, но не для других.

Я столкнулся с той же проблемой и потратил почти 6 часов, чтобы найти обходной путь. Я не хочу, чтобы кто-то еще снова тратил свое время. Увидев все возможные ответы. Вот как я это исправил:

Я привязал метод к событию main / parent DataGrid Loaded . Определение метода:

private void FrameworkElement_OnLoaded(object sender, RoutedEventArgs e)
{
    var grid = sender as DataGrid;
    if (grid != null && grid.CurrentItem == null && grid.SelectedItem != null)
    {
        grid.CurrentItem = grid.SelectedItem;
    }
    else if (grid != null) //Fix when IsSynchronizedWithCurrentItem=True
    {
        var selectedItem = grid.SelectedItem;
        grid.CurrentItem = null;
        grid.SelectedItem = null;
        grid.CurrentItem = selectedItem;
        grid.SelectedItem = selectedItem;
    }
}
0 голосов
/ 07 февраля 2017

Я понимаю, что этот вопрос старый, но у меня 10-летний контракт, в котором используются WPF и XAML, и я столкнулся с той же проблемой, когда пользователям пришлось дважды щелкнуть строку в таблице данных, чтобы активировать событие нажатия кнопки мыши.Это связано с тем, что сетка данных использует первый щелчок для выбора строки и второй щелчок для запуска события.Я нашел гораздо более простое решение, которое работает для моего приложения:

        PreviewMouseLeftButtonDown="MainDataGrid_OnMouseLeftButtonDown"

Это вызывает событие нажатия левой кнопки мыши при первом нажатии.Вот как это выглядит в настройке сетки данных:

     <DataGrid Name="MainDataGrid" IsSynchronizedWithCurrentItem="True" SelectionMode="Extended" SelectionUnit="FullRow" 
         ...removed other options for brevity
         PreviewMouseLeftButtonDown="MainDataGrid_OnMouseLeftButtonDown"
         ...removed other options for brevity
         RowHeight="30" BorderThickness="0" Background="#99F0F0F0"  Grid.Column="{Binding GridColumn, Mode=TwoWay}" Grid.Row="1">

Я использовал это вместо MouseLeftButtonDown.Приветствия.

0 голосов
/ 16 апреля 2015

Возможно, это не вариант для вас, но установка IsReadonly = true решила эту проблему для меня.

0 голосов
/ 15 августа 2013

Другое решение - создать собственную кнопку. Одно из преимуществ этого: вам не нужно подключать события для каждой кнопки.

public class FireOnPreviewButton : Button
{

    #region Constructor

    public FireOnPreviewButton()
    {
        PreviewMouseLeftButtonDown += OnLeftMouseButtonDownPreview;
    }

    #endregion

    #region Event Handler

    private void OnLeftMouseButtonDownPreview(object sender, MouseButtonEventArgs e)
    {
        // Prevent the event from going further
        e.Handled = true;

        // Invoke a click event on the button
        var peer = new ButtonAutomationPeer(this);
        var invokeProv = peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
        if (invokeProv != null) invokeProv.Invoke();
    }

    #endregion

}
0 голосов
/ 10 мая 2012

У меня была та же проблема - я использовал изображение в столбце шаблонов и событие MouseDown, но мне пришлось дважды щелкнуть.Поэтому я вызвал обработчик событий в конструкторе, и он сработал для меня.

Вы можете попробовать это:

constructor() {
    datagridname.AddHandler(Button.ClickEvent, new RoutedEventHandler(Button_Click), true);
}
...