Вы можете использовать пользовательское перенаправленное событие и подключить соответствующие обработчики в таком поведении:
public class UserSelectionChangedEventArgs : RoutedEventArgs
{
public UserSelectionChangedEventArgs( RoutedEvent id, SelectionChangedEventArgs args , bool changedByUser) :base(id)
{
SelectionChangedByUser = changedByUser;
RemovedItems = args.RemovedItems;
AddedItems = args.AddedItems;
}
public bool SelectionChangedByUser { get; set; }
public IList RemovedItems { get; set; }
public IList AddedItems { get; set; }
}
public delegate void UserSelectionChangedEventHandler( object sender, UserSelectionChangedEventArgs e );
public class UserSelectionChangedBehavior : Behavior<Selector>
{
private bool m_expectingSelectionChanged;
public static readonly RoutedEvent UserSelectionChangedEvent = EventManager.RegisterRoutedEvent( "UserSelectionChanged", RoutingStrategy.Bubble, typeof( UserSelectionChangedEventHandler ), typeof( Selector ) );
public static void AddUserSelectionChangedHandler( DependencyObject d, UserSelectionChangedEventHandler handler )
{
( (Selector) d ).AddHandler( UserSelectionChangedEvent, handler );
}
public static void RemoveUserSelectionChangedHandler( DependencyObject d, UserSelectionChangedEventHandler handler )
{
( (Selector) d ).RemoveHandler( UserSelectionChangedEvent, handler );
}
private void RaiseUserSelectionChangedEvent( UserSelectionChangedEventArgs args )
{
AssociatedObject.RaiseEvent( args );
}
protected override void OnAttached()
{
AssociatedObject.PreviewKeyDown += OnKeyDown;
AssociatedObject.PreviewKeyUp += OnKeyUp;
AssociatedObject.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
AssociatedObject.PreviewMouseLeftButtonUp += OnMouseLeftButtonUp;
AssociatedObject.SelectionChanged += OnSelectionChanged;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.PreviewKeyDown -= OnKeyDown;
AssociatedObject.PreviewKeyUp -= OnKeyUp;
AssociatedObject.PreviewMouseLeftButtonDown -= OnMouseLeftButtonDown;
AssociatedObject.PreviewMouseLeftButtonUp -= OnMouseLeftButtonUp;
AssociatedObject.SelectionChanged -= OnSelectionChanged;
base.OnDetaching();
}
private void OnMouseLeftButtonUp( object sender, MouseButtonEventArgs e )
{
m_expectingSelectionChanged = false;
}
private void OnKeyDown( object sender, KeyEventArgs e )
{
m_expectingSelectionChanged = true;
}
private void OnKeyUp( object sender, KeyEventArgs e )
{
m_expectingSelectionChanged = false;
}
private void OnMouseLeftButtonDown( object sender, MouseButtonEventArgs e )
{
m_expectingSelectionChanged = true;
}
private void OnSelectionChanged( object sender, SelectionChangedEventArgs e )
{
RaiseUserSelectionChangedEvent( new UserSelectionChangedEventArgs( UserSelectionChangedEvent, e, m_expectingSelectionChanged ) );
}
}
В XAML вы можете просто подписаться на UserSelectionChangedEvent следующим образом:
<ListBox ItemsSource="{Binding Items}" b:UserSelectionChangedBehavior.UserSelectionChanged="OnUserSelectionChanged">
<i:Interaction.Behaviors>
<b:UserSelectionChangedBehavior/>
</i:Interaction.Behaviors>
Обработчик:
private void OnUserSelectionChanged( object sender, UserSelectionChangedEventArgs e )
{
if(e.SelectionChangedByUser)
{
Console.WriteLine( "Selection changed by user" );
}
else
{
Console.WriteLine( "Selection changed by code" );
}
}
Это всего лишь идея. Возможно, вам даже не понадобится поведение, и вы просто определите прикрепленное перенаправленное событие. Но тогда я понятия не имею, где хранить флаг m_expectingSelectionChanged. Я также не знаю, работает ли это во всех случаях. Но, возможно, это даст вам отправную точку.