Csi
Csi

Reputation: 526

Listbox selection hides other mouse event

Hello Stackoverflowers,

I have a System.Windows.Control.ListBox. It's doing a great job but i would like to had a few behaviours when i select certain types of items.

I can't do it in the bind property for SelectedItem because my Listbox's View Model (Foo) doesn't know all the needed datas for the work i want (some coming from another ViewModel : Bar).

My two mentioned ViewModel are field of a bigger class Zot, in order for Zot to access the content of both Foo and Bar

I foward click event in Foo and Bar to Zot using Interaction.Triggers, EventTrigger and InvokeCommandAction. It's working great for Bar (which is a canvas). However i have trouble with the Listbox.

After testing events SelectionChanged, MouseDown and Click, it appears that MouseDown is triggered if I click on the grid wrapping the listbox but not when i click on the ListBox. It feels like the embedded selection in the Listbox is conflicting with other events.

Anyone got any idea to do specific actions depending on the selected item, in a different viewmodel ?

Thanks a lot

EDIT :

Here is the XAML for the Listbox (in ToolboxView.xaml)

     d:DataContext="{d:DesignInstance viewModels:ToolboxViewModel}">
       <Grid>
          <ListBox
                ItemsSource="{Binding Tools}"
                SelectedItem="{Binding SelectedTool}"
                x:Name="ToolView" >

            <ListBox.ItemTemplate>
                <DataTemplate DataType="interfaces:IBuilder">
                    <TextBlock 
                        FontWeight="DemiBold"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Text="{Binding Name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

Here is the event on the Listbox, from the main window xaml (which view model holds the listbox view model, i explain why below). However the event is never triggered. Later in the same file, 3 similar event works perfectly (on a canvas). I tried to use MouseDown instead of SelectionChanged, it is triggered when i click in the grid containing the listbox but isn't trigger when i click listbox.

(in MainWindow.xaml)

<DockPanel>
        <views:ToolboxView DockPanel.Dock="Left"
                                Width="120" 
                                IsHitTestVisible="True"
                                DataContext="{Binding ToolBoxViewModel}" 
                                x:Name="ToolboxView">

            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged">
                    <i:InvokeCommandAction Command="{Binding Path=DataContext.SelectionChangedCommand,  RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                           CommandParameter="{Binding ElementName=ToolboxOverlayView}"/>
                </i:EventTrigger>
           </i:Interaction.Triggers>

Now what i called "embeded selection" is the behaviour of the Listbox where i can highlight an element inside the listbox and select it. This works perfectly with the code above (i can select my tools, the property binded in ViewModel change accordingly). What i'm trying to do is firing the SelectionChanged event to do special work when a certain category of elements inside the listbox are selected.

I could do this in the setter of the property binded to Listbox's ItemSelected but the work to do need datas unknown from the listbox view model, which is why i have a mainwindow view model that holds the view model of the listbox and i try to get the SelectionChanged event in the main window view model (and another view model).

Tell me if it's not clear please.

Upvotes: 0

Views: 103

Answers (1)

nkoniishvt
nkoniishvt

Reputation: 2521

You're trying to set a SelectionChanged event in your ToolboxView that does not know any SelectionChanged event.

You could create two DP in ToolboxView that stores the command and its parameter:

#region SelectionChangedCommand 

public ICommand SelectionChangedCommand
{
    get { return (ICommand)GetValue(SelectionChangedCommandProperty); }
    set { SetValue(SelectionChangedCommandProperty, value); }
}

private readonly static FrameworkPropertyMetadata SelectionChangedCommandMetadata = new FrameworkPropertyMetadata {
    DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};

public static readonly DependencyProperty SelectionChangedCommandProperty = 
    DependencyProperty.Register("SelectionChangedCommand", typeof(ICommand), typeof(ToolboxView), SelectionChangedCommandMetadata);
#endregion


#region SelectionChangedCommandParameter 

public Object SelectionChangedCommandParameter
{
    get { return (Object)GetValue(SelectionChangedCommandParameterProperty); }
    set { SetValue(SelectionChangedCommandParameterProperty, value); }
}

private readonly static FrameworkPropertyMetadata SelectionChangedCommandParameterMetadata = new FrameworkPropertyMetadata {
    DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};

public static readonly DependencyProperty SelectionChangedCommandParameterProperty = 
    DependencyProperty.Register("SelectionChangedCommandParameter", typeof(Object), typeof(ToolboxView), SelectionChangedCommandParameterMetadata);
#endregion

Then in the ToolboxView.xaml:

<Grid>
    <ListBox
        ItemsSource="{Binding Tools}"
        SelectedItem="{Binding SelectedTool}"
        x:Name="ToolView" >
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <i:InvokeCommandAction Command="{Binding Path=SelectionChangedCommand,  RelativeSource={RelativeSource AncestorType={x:Type ToolboxView}}}"
                                       CommandParameter="{Binding Path=SelectionChangedCommandParameter,  RelativeSource={RelativeSource AncestorType={x:Type ToolboxView}}}"/>
            </i:EventTrigger>
       </i:Interaction.Triggers>
        <ListBox.ItemTemplate>
            <DataTemplate DataType="interfaces:IBuilder">
                <TextBlock 
                    FontWeight="DemiBold"
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Text="{Binding Name}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

And use it in MainWindow.xaml:

<views:ToolboxView DockPanel.Dock="Left"
                    Width="120" 
                    IsHitTestVisible="True"
                    DataContext="{Binding ToolBoxViewModel}" 
                    x:Name="ToolboxView"
                    SelectionChangedCommand="{Binding Path=DataContext.SelectionChangedCommand,  RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                    SelectionChangedCommandParameter="{Binding ElementName=ToolboxOverlayView}"/>

Upvotes: 1

Related Questions