I have a button above a listbox which has it's items in a horizontal allignment. If my button has focus and I press the down key on the keyboard then the listbox get focus. If I then press key up then the listbox still has focus. Can this behaviour be changed so when I press key up my button has focus again?
EDIT: I should add I'm using MVVM so would like to keep the solution out of codebehind if possable.
Below is the complete code for my listbox.
<ListBox Grid.Row="2" ItemsSource="{Binding Movies}" TextSearch.TextPath="Title" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="poster">
<Image x:Name="posterImage" RenderOptions.BitmapScalingMode="LowQuality" Source="{Binding Poster}" Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualHeight}">
</Image>
<TextBlock Text="{Binding PosterOverlayText}" Style="{DynamicResource PosterOverlayText}" Width="{Binding ActualWidth, ElementName=posterImage}"/>
<Grid.LayoutTransform>
<TransformGroup>
<ScaleTransform x:Name="st" ScaleX="0.85" ScaleY="{Binding ScaleX, RelativeSource={RelativeSource Self}}"/>
</TransformGroup>
</Grid.LayoutTransform>
<Grid.InputBindings>
<MouseBinding Command="{x:Static Commands:MediaFiles.PlaySelectedMovie}" Gesture="LeftDoubleClick" />
</Grid.InputBindings>
</Grid>
<DataTemplate.Resources>
<CubicEase x:Key="ease" EasingMode="EaseOut"/>
</DataTemplate.Resources>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.3"
EasingFunction="{StaticResource ease}"
Storyboard.TargetName="st"
Storyboard.TargetProperty="ScaleX"
To="1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.3"
EasingFunction="{StaticResource ease}"
Storyboard.TargetName="st"
Storyboard.TargetProperty="ScaleX"
To="0.85"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.InputBindings>
<KeyBinding Command="{x:Static Commands:MediaFiles.PlaySelectedMovie}" Gesture="ENTER"/>
</ListBox.InputBindings>
</ListBox>
Don't know if there is a straight-forward MVVM accepted solution to this problem. The reason is that ListBox actually uses the key up and key down events to navigate through the list items (which is the desired effect most of the times) whereas the buttons will let the events go to the FocusManager class.
However, as for everything out there, there are workarounds so here's how I would do it:
First of all you need to intercept the Key-Down event and look for directional inputs (up-down-left-right). I would think that you would still like to navigate with the keys in your list so, in the event handler I would make sure to test if I am on the first (or last) element and then use the MoveFocus() method with TraversalRequest - FocusNavigationDirection.Up / Down / Next / Previous to move the focus.
Last, to ensure your code-behind is clean, create a new ListBox derived control and have your event there. Actually, in the derived control, don't use the event, overide OnKeyDown method. This way, you are writing the focus logic in your custom control and not the View.
Code:
protected override void OnKeyDown(KeyEventArgs e)
{
if ((e.Key == Key.Up ||e.Key == Key.Left) && SelectedIndex == 0)
{
//.Previous will navigate correctly to the last element
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous));
return;
}
if (e.Key == Key.Down && this.SelectedIndex == this.Items.Count - 1)
{
//.Next will navigate to the first item in the list rather than skip to the next control. We will use Down or Right.
//this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
return;
}
if (e.Key == Key.Right && this.SelectedIndex == this.Items.Count - 1)
{
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right));
return;
}
base.OnKeyUp(e);
}
Related
I have a problem with an animation within a template of an ItemsControl that is part of the template of another ItemsControl. I want a path, that is representing an Icon, to change its color and constantly rotate when a certain condition becomes true.
The DataTrigger generally works, causing the Fill of the Path changing from Gray to LightGreen when the producing Property changes to true. However, the animation does not start. When I let the animation start with the Loaded Event (as you can see in the commented section), it starts properly. So I know that the animation, as well as the DataTrigger, is configured correctly.
When I put the same Path (just copy and paste) in the outside ItemsControl and change the DataTrigger to a Property of the corresponding DataType, the animation also works as expected. So there seems to be a problem with the nested ItemsControls, but I have no idea what it might be.
<ItemsControl ItemsSource="{Binding Computers}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type models:ClientComputerWrapper}">
<Border Margin="5" BorderBrush="Black" BorderThickness="1" Padding="5">
<StackPanel>
<!-- Some Content -->
<ItemsControl ItemsSource="{Binding PlcReaderStatuses}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type resources:PlcReaderStatusResource}">
<DockPanel LastChildFill="False">
<!-- Some Content -->
<Path DockPanel.Dock="Left" HorizontalAlignment="Left" Data="{StaticResource GearIconGeometry}" Stretch="Uniform" RenderTransformOrigin="0.5, 0.5">
<Path.RenderTransform>
<RotateTransform x:Name="gearPathTransform"/>
</Path.RenderTransform>
<Path.Style>
<Style TargetType="Path">
<Setter Property="Fill" Value="Gray"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsProducing}" Value="True">
<Setter Property="Fill" Value="LightGreen"/>
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="rotateStoryBoard">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)" To="360" Duration="0:0:2" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="rotateStoryBoard"/>
</DataTrigger.ExitActions>
</DataTrigger>
<EventTrigger RoutedEvent="Loaded">
<!--<BeginStoryboard x:Name="rotateStoryBoard">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Path.RenderTransform).(RotateTransform.Angle)" To="360" Duration="0:0:2" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>-->
</EventTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I've finally found a solution. After trying to replace the DoubleAnimation with a ColorAnimation, using (Path.Fill).(SolidColorBrush.Color) as TargetProperty, I received an error that the path is not pointing to a DependencyProperty. This was only solved when I defined the SolidColorBrush explicitly in a Setter which led my to try the same with the RenderTransform of the Path:
<Path.Style>
<Style TargetType="Path">
<Setter Property="RotateTransform">
<Setter.Value>
<RotateTransform x:Name="gearPathTransform"/>
</Setter.Value>
</Setter>
<!-- ... -->
</Style>
Afterwards the animation works as expected. I still don't know why this is only necessary in the inner ItemsControl and it is also nasty that there is no error as is for the ColorAnimation, but at least it is working now.
I have got a ListBox.ItemTemplate that has got a ToggleButton and inside of it a checkbox and a ProgressBarEdit from devexpress.
Then I have a style that targets the checkbox. When the mouse is over the checkbox it changes its opacity.
The double animation and the binding works fine, however the listbox itemssource is bound and I would like to make all the checkboxes opacity change when the mouse is over any checkbox and not just one.
I tried to bind Storyboard.TargetProperty to my viewmodel property but it is not a dependency property so I cannot do it.
This is the animation:
<Style x:Key="FadeOutButton" TargetType="{x:Type CheckBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=chkImport}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1"
Storyboard.TargetProperty="Opacity"
To="1" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1"
Storyboard.TargetProperty="Opacity"
To="0.02" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
This is part of the ListBox control:
<ListBox x:Name="FileDetailsListBox"
Grid.Column="2"
BorderThickness="0"
ItemsSource="{Binding FileDetailsList}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<ToggleButton x:Name="FileToggleButton"
Margin="-1,0,-1,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
BorderThickness="0,0">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox x:Name="chkImport"
Margin="0,0,0,3"
HorizontalContentAlignment="Center"
IsChecked="{Binding Import,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
Opacity="{Binding DataContext.ImportOpacity,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ElementName=ImportView}"
Style="{StaticResource FadeOutButton}" />
<dxe:ProgressBarEdit Grid.Row="2"
Height="20"
Margin="-3,0,-3,0"
EditValue="{Binding ProgressValue}"
ShowBorder="False"
StyleSettings="{Binding IsMarquee,
Converter={StaticResource conv}}" />
</Grid>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
How can I change all the checkboxes opacity from the Listbox when Control.MouseEnter is triggered?
I thought the way to go was binding the ImportOpacity property from my viewmodel in the style, but the animation does not allow it.
Thanks
Update:
I cannot post images because I am new here, but I would like to change the Opacity for all the checkboxes created by the datatemplate when the mouse enter in any checkbox. The animation works fine for individual checkboxes like the code does at the moment.
My viewmodel has got a property called "ImportOpacity" and it is bound to the checkbox.opacity (you can see it in the xaml above) My idea was to use this property to make the Opacity from 0 to 100 when the mouse is over any checkbox.
Instead of animate the Opacity property of the CheckBox and bind it to ImportOpacity with TwoWay mode, I think you should animate the ImportOpacity property in your ViewModeldirectly.
Here is a reference about how to animate property in ViewModel.
Is there any opportunity to set event handler inside xaml without using c#, powershell etc.?
For example I would like to set text of another control after click. Below is a "pseudo code" of what I want to do:
<Button Content="Set value = text1" OnClick="txt1.Text = text1" />
<Button Content="Set value = text2" OnClick="txt1.Text = text2" />
<Textbox Name="txt1" />
You can write inline c# in xaml. Altho that is just something you should rather be avoiding at all costs. If you absolutely have to, you could do something like:
<StackPanel>
<Button Content="Set value = text1" Click="InlineHandler" />
<Button Content="Set value = text2" Click="InlineHandler" />
<TextBox Name="txt1" />
<x:Code>
<![CDATA[
private void InlineHandler(object sender, RoutedEventArgs e) {
var btn = sender as Button;
if (btn == null)
return;
txt1.Text = btn.Content.ToString() == "Set value = text1" ? "text1" : "text2";
}
]]>
</x:Code>
</StackPanel>
MSDN Link - Code-Behind and XAML in WPF
In simple terms, you're just defining the event handler inline in xaml than in the code-behind.
Again do not resort to this approach unless you're proving a point.
there is a solution with EventTrigger. Though it does not work with TextBox, because the Text-Property is not animatable, you could change the text of a textblock with some buttons without any code behind.
But: This is not a nice solution, and you should either use some short codebehind (preferable in an attached behavior) or a small viewModel where you bind to some property. The last one should be the cleanest solution, the codebehind is the shortest.
for feasability, here's the template with which you can change the Text of a Control with pure xaml:
<ControlTemplate x:Key="MyTemplate" TargetType="Control">
<StackPanel Orientation="Horizontal">
<Button x:Name="buttonValueText1" Content="Set value = text1" Width="50" Height="50"/>
<Button x:Name="buttonValueText2" Content="Set value = text2" Width="50" Height="50"/>
<TextBlock x:Name="textBox" Height="30" Width="100" Margin="5"/>
</StackPanel>
<ControlTemplate.Triggers>
<EventTrigger SourceName="buttonValueText1" RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames Storyboard.TargetName="textBox" Storyboard.TargetProperty="Text">
<DiscreteStringKeyFrame Value="Text1" KeyTime="0:0:0.1"/>
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger SourceName="buttonValueText2" RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames Storyboard.TargetName="textBox" Storyboard.TargetProperty="Text">
<DiscreteStringKeyFrame Value="Text2" KeyTime="0:0:0.1"/>
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
To give you an idea of how you maybe could solve this
<StackPanel>
<ToggleButton Name="B1" Width="50" Height="50" Content="Text1"/>
<ToggleButton Name="B2" Width="50" Height="50" Content="Text2"/>
<TextBlock Width="50" Height="50" >
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=B1, Path=IsChecked}" Value="True">
<Setter Property="Text" Value="{Binding ElementName=B1, Path=Content}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=B2, Path=IsChecked}" Value="True">
<Setter Property="Text" Value="{Binding ElementName=B2, Path=Content}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
Writing the XAML handler in PowerShell is a steep cliff. Writing the whole UI isn't. Myself and Joel Bennett (aka Jaykul) merged together two wildly popular solutions for this (WPK and PowerBoots) into ShowUI.
New-StackPanel {
New-Button "Set Text Value 1" -On_Click { $textBlock.Text = 1 }
New-Button "Set Text Value 2" -On_Click { $textBlock.Text = 2 }
New-TextBlock -Name textBlock
} -show
Because PowerShell can coerce many more types than XAML, it's actually a lot more convenient for rapid development of a user interface.
I'm trying to get a message panel animated in WPF but has so far achieved no success.
This is the situation:
I have a user control with a StackPanel containing an ItemsControl bound to an (observable) collection in the control's View Model object (ViewModel.Messages).
When I need to present the user with messages I ad those (as MessageVM instances) to the observable collection.
The ItemsControl's visibility is bound to an integer property called ViewModel.CountVisibleMessages and there's a converter taking care of translating 0 to Visibility.Hidden and positive values to Visibility.Visible.
This works just fine. When a message gets added to the collection the StackPanel automatically becomes visible and as the user (or a timer) removes the last message it gets hidden. The StackPanel height is automatically adjusted to fit all messages of course.
To make everything look nicer I would prefer it if the StackPanel resized itself using an animation running for, say, 300 ms. (Ultimately I would also like it to accelerate and deccelerate but that's beyond my ambition right now.
I have experimented for a few hours now but I feel I'm not even close.
Below is my current (not even close to working) XAML at the moment:
<StackPanel Orientation="Vertical"
VerticalAlignment="Top"
Visibility="{Binding CountVisibleMessages, Converter={StaticResource IntToVisibility}}"
Height="Auto"
Background="{DynamicResource HmiBackColorLightBrush}">
<StackPanel.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding CountVisibleMessagesChanged}" Value="True" ><!-- I suppose I shopuld've used a Routed Event here but I just needed to get it triggered -->
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Margin.Bottom"
From="100" <!-- Just a made up value to test the concept -->
To="0"
Duration="0:0:0:3"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<ItemsControl ItemsSource="{Binding Messages}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{DynamicResource Message}">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="15" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Text}" Margin="3" Style="{Binding MessageType, Converter={StaticResource MessageTypeToStyle}, ConverterParameter={x:Type TextBlock}}" /> <!-- using dynamic styling here -->
<RadioButton Grid.Column="1" Style="{DynamicResource HmiCloseMessageButton}" IsChecked="{Binding IsVisible, Converter={StaticResource BoolToVisibility}, ConverterParameter=true}" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
(I do realize the above XAML won't get the StackPanel to auto-resize slowly. It's just an experiment to get anything happening).
This can't be too difficult I suppose (it's a pretty standard UI behavior in many programs) so I'd appreciate it if anyone could point me in the right directions.
Cheers
Are you sure you want to adjust the bottom margin? The stack panel VerticalAlignment is top. If you want to change the Height then bind your StoryBoard Property to Height. Do you know if your StoryBoard is firing?
The key point is ExitActions are necessary for EnterAction based dataTrigger animations. So the following seems to be working in my case ....
<StackPanel Grid.Row="0" Height="100" x:Name="MyGrid">
<StackPanel.Style>
<Style>
<Style.Triggers>
<DataTrigger
Binding="{Binding ElementName=MyCheckBox,
Path=IsChecked}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.Target="{Binding
RelativeSource={RelativeSource
AncestorType={x:Type
StackPanel}},
BindsDirectlyToSource=True}"
Storyboard.TargetProperty="Height"
From="100"
To="200"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.Target="{Binding
RelativeSource={RelativeSource
AncestorType={x:Type
StackPanel}},
BindsDirectlyToSource=True}"
Storyboard.TargetProperty="Height"
To="100"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
<CheckBox x:Name="MyCheckBox" Grid.Row="1" />
Let me know if this helps.
I have a simple ListBox.ItemTemplate containing a Label and a TextBox bound to a CSLA Bindable List. When I select the TextBox the CurrentItem does not change, it only changes if I select the Label. I have IsSynchronizedWithCurrentItem='True'.
<ListBox x:Name="ItemsDataGrid"
ItemsSource="{Binding Source={StaticResource AuditItems},Path=Items}"
IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Content="{Binding Path=TypeRef}" />
<TextBox x:Name="TextBoxQty"
Grid.Column="1"
Text="{Binding Path=TaliQty}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Try adding this to your ListBox. It selects the item any time any contained element (like TextBox) gets keyboard focus. A similar method could also be used with just a simple setter in the Trigger but that tends to interfere with the CurrentItem setting on the ICollectionView:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="SetSelected">
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected">
<DiscreteBooleanKeyFrame KeyTime="0:00" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="SetSelected"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
This is happening because the TextBox is handling the MouseDown event. As it is set to bubble up it will not reach the containing ListBoxItem. The simplest way to fix this would be to just handle the selection of the ListBoxItems in the PreviewMouseDown, which will occur and tunnel down before the actual MouseDown event bubbles up.
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="PreviewMouseDown"
Handler="ListBoxItem_PreviewMouseDown" />
</Style>
</ListBox.ItemContainerStyle>
And in the Code behind for the xaml file:
private void ListBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var item = (sender as ListBoxItem);
if (item != null)
item.IsSelected = true;
}