Почему мои пользовательские элементы управления не всегда получают события MouseEnter? - PullRequest
1 голос
/ 21 мая 2019

Хорошо, я довольно новичок в WPF и столкнулся с очень странной проблемой.Соответствующий раздел моего XAML определяет Border вокруг ScrollViewer вокруг StackPanel, который заполняется с помощью ItemsControl, который затем связывается с данными с CollectionViewSource, который, в свою очередь, оборачивает стандартную ObservableCollection.ItemsControl определяет DataTemplate, который содержит только один тег: пользовательский элемент управления, который я назвал StackElement.Я обрабатываю три события из этого элемента управления - MouseEnter, MouseLeave и PreviewMouseLeftButtonUp.Эти события могут произойти, но сделать это ненадежно.

Например, после добавления некоторых новых StackElements событие MouseEnter, как правило, не запускается на first StackElement, пока я не наведу на несколько других.Как только MouseOver удается запустить один раз, он продолжает корректно запускать этот StackElement с этого момента.

Однако первое наведение мыши на StackElement не всегда дает сбой.Если я подойду к StackElements из ниже и сначала попробую последний, он всегда будет срабатывать.Когда я это делаю, иногда первый срабатывает, а второй не срабатывает.Когда-то им обоим удавалось работать правильно, но это случается нечасто.

Я не многопоточен, ни один из моих родительских элементов управления не обрабатывает свои собственные события, все обработчики событий состоят только из WriteLine ()оператор для целей отладки, а код StackElement также не обрабатывает никаких событий.

Я попытался отделить ItemsControl от CollectionViewSource, чтобы связать его непосредственно с ObservableCollection, который не сделал ничего, кроме(как я и ожидал) обойти функции сортировки, которые я добавил в ViewSource.Я попытался обработать события в самом классе StackElement, в дополнение к тому, что они были привязаны к другим элементам управления, содержащимся в StackElement.Я попытался использовать DataTriggers, который, если я помню, работал как ожидалось, но мне нужно включить более продвинутую логику, такую ​​как множественный выбор и невозможность слегка выделить уже выбранный StackElement.

Для контекста я намереваюсьиспользуйте эти события, чтобы слегка выделить StackElements, когда пользователь перетаскивает на них мышь, и сильно выделить их при нажатии мыши - в основном мне нужно что-то, похожее на Windows File Explorer.Из того, что я видел, это не может быть выполнено элегантным способом только с DataTriggers.

Вот мои обработчики событий (в MainWindow.xaml):

private void StackElement_OnPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    Console.WriteLine("OnPreviewMouseLeftButtonUp fired for a StackElement.");
}

private void StackElement_OnMouseEnter(object sender, MouseEventArgs e)
{
    Console.WriteLine("OnMouseEnter fired for a StackElement.");
}

private void StackElement_OnMouseLeave(object sender, MouseEventArgs e)
{
    Console.WriteLine("OnMouseLeave fired for a StackElement.");
}

Вот как яm добавление в связанную коллекцию (для тестирования, поэтому она подключена к случайной кнопке):

private void Btn_File_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    InitiativeStackElement t = new InitiativeStackElement(new Entity("TestName", 10, 11, 12, 13, null)); //InitiativeStackElement implements INotifyPropertyChanged so the databindings work
    _entityProvider.Elements.Add(t); //_entityProvider is just a reference to a XAML-defined resource class, which is loaded up in the constructor so I don't have to call TryGetResource() whenever I want to use it. it's currently used for testing purposes only
}

Наконец, вот часть моего XAML, содержащего StackElements:

<Border Grid.Row="1"
        Margin="0,1,0,0" 
        Style="{StaticResource StandardBorder}">
    <ScrollViewer Name="Scv_InitiativeStack">
        <StackPanel Name="Stp_InitiativeStack">
            <ItemsControl Name="Its_InitiativeStack" ItemsSource="{Binding Source={StaticResource SortedInitiativeStack}}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <con:StackElement Element="{Binding}" PreviewMouseLeftButtonUp="StackElement_OnPreviewMouseLeftButtonUp"                                           MouseEnter="StackElement_OnMouseEnter" MouseLeave="StackElement_OnMouseLeave"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>
    </ScrollViewer>
</Border>

Класс StackElement просто определяет один объект DependencyProperty типа InitiativeStackElement.Свойства этого объекта привязаны к нескольким элементам управления в StackElement, который всегда отображается правильно.Меня смущает поведение событий.

Как описано, я ожидаю, что событие MouseEnter сработает всякий раз, когда мышь перетаскивают на StackElement.Тем не менее, он срабатывает только после того, как я выполню, казалось бы, случайные условия, которые не должны влиять на его функциональность, например, сначала навести курсор на другой StackElement.Нет сообщений об ошибках.

1 Ответ

0 голосов
/ 21 мая 2019

Хорошо, я смог получить желаемую функциональность с помощью ListBox:

<Window.Resources>
    <DataTemplate x:Key="InitiativeStackTemplate">
        <con:StackElement Element="{Binding}"/>
    </DataTemplate>
</Window.Resources>

<Border Margin="0,1,0,0" 
        Grid.Row="1"
        Style="{StaticResource StandardBorder}">
    <ScrollViewer Name="Scv_InitiativeStack">
        <ListBox Name="Lbx_InitiativeStack" 
                 SelectionMode="Extended"
                 ItemsSource="{Binding Source={StaticResource SortedInitiativeStack}}" 
                 ItemTemplate="{StaticResource InitiativeStackTemplate}"
                 HorizontalContentAlignment="Stretch"/>
    </ScrollViewer>
</Border>

Все работает как положено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...