WPF Listview SelectionChanged событие

У меня есть привязка ListView к ItemsSource. Почему событие SelectionChanged срабатывает при событиях load/databound? Я предполагаю, что это происходит потому, что выбраны элементы по умолчанию, то есть индекс 0.

Как я могу отключить это, потому что при выборе элемента обновлялись другие источники с данными.

Спасибо Petrus

Ответ 1

спасибо за ответы.

Когда я помещаю точку останова на событие SelectionChanged, он прерывает процедуру там до того, как экран будет полностью загружен. Вы также увидите, что первая строка будет выбрана впоследствии в списке. Я не привязываюсь к элементу SelectedIndexValue, как вы можете видеть в коде. DataContext для списка - это ReadonlyCollection

В моем событии SelectionChanged, как вы можете видеть, я уведомляю другие объекты, которые будут загружены данными, относящимися к выбранному элементу. Я хочу, чтобы это произошло только при выборе одного из них, но не по умолчанию. Я должен иметь эти ListViews, представляющие аналогичные данные, но при загрузке ни один из них не должен иметь выбранный элемент.

Я заметил, что по умолчанию выбранный индекс установлен в -1 в окне свойств для Listview. Я даже могу установить этот код в событии List_Loaded, но к тому времени уже произошел первый SelectionChanged.

<ListView PreviewMouseDown="ActiveCasesView_MouseDown" x:Name="ActiveCasesView"
                     DataContext="{StaticResource ActiveCasesViewSource}"
                     ItemsSource="{Binding}"
                     ItemTemplate="{StaticResource CasesItemTemplate}"
                     SelectionMode="Single"
                     SelectionChanged="ActiveCasesView_SelectionChanged"
                     ScrollViewer.CanContentScroll="True" 
                     ScrollViewer.VerticalScrollBarVisibility="Auto" >
</ListView>

private void ActiveCasesView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (mouseClicked)
            if (e.AddedItems.Count > 0)
                App.Messenger.NotifyColleagues(App.MSG_SELECT_ACTIVE_CASE, ((CaseViewModel)ActiveCasesView.SelectedItem).CaseNumber);
    }

Я добавил PreviewMouseDown, чтобы установить индикатор, который я нажал на listview в событии SelectionChanged. Это помогает, но я не уверен, что это лучшее решение.

Спасибо Petrus

Ответ 2

ListView не должен запускать SelectionChange, если вы только устанавливаете свойство ItemsSource. Однако, если вы привязываете свойство SelectedIndex к свойству объекта dataContext, выбор будет перемещаться к индексу, указанному свойством binded.

это не вызывает событие Selector_OnSelectionChanged при загрузке страницы:

<ListView SelectionChanged="Selector_OnSelectionChanged" 
                  ItemsSource="{Binding Path=Items}"
                  ></ListView>

но это делает:

<ListView SelectionChanged="Selector_OnSelectionChanged" 
                  SelectedIndex="{Binding Path=SelectedIndexValue}"
                  ItemsSource="{Binding Path=Items}"
                  ></ListView>

потому что SelectedIndex установлен в SelecteIndexValue посредством привязки.

Чтобы избежать этого и по-прежнему поддерживать привязки в вашей разметке, установите значение SelectedIndexValue вашего объекта dataContext равным -1 перед привязкой (до того, как InitializeComponent() вызывается в вашем конструкторе форм).

Надеюсь, что это поможет.

Ответ 3

Я не знаю, нужна ли вам помощь в этом случае, но я решил эту проблему, создав переменную, которая отслеживает выбранный индекс, в моем случае - когда первоначально привязана всегда 0, поэтому мне немного легче сделать, однако, если вы сообщите viewmodel соответствующего индекса, я просто добавил

ComboBox box = e.OriginalSource as ComboBox;
if (_previousIndex == cb.SelectedIndex) return;
//do stuff you need to do with a new SelectedIndex

Ответ 4

Вы можете попробовать установить свойство SelectedIndex равным -1 в вашей привязке, но это также не изящное решение.

<ListView PreviewMouseDown="ActiveCasesView_MouseDown" x:Name="ActiveCasesView"
                     DataContext="{StaticResource ActiveCasesViewSource}"
                     ItemsSource="{Binding}"
                     ItemTemplate="{StaticResource CasesItemTemplate}"
                     SelectionMode="Single"
                     SelectionChanged="ActiveCasesView_SelectionChanged"
                     ScrollViewer.CanContentScroll="True" 
                     ScrollViewer.VerticalScrollBarVisibility="Auto" 
**SelectedIndex="-1"**>
</ListView>

Я пытался воспроизвести ваше поведение, но безуспешно. Каков тип коллекции ItemsSource, к которой вы привязываетесь?

Ответ 5

вы можете использовать событие, загруженное в окно, чтобы заблокировать действие

bool loaded = false;

window.Loaded += new RoutedEventHandler(MainWindow_Loaded);

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
   windowLoaded = true;
}

private void ActiveCasesView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{

if(!loaded)
return ;

//do actions here ....

}