Interaction.Triggers fail in MVVM listbox view - wpf

The xaml below works correctly when I click (MouseDown) anywhere on the background of the listbox. The problem is that I can not get it to work when I click on any single item in the listbox. I've tried putting the trigger code inside the border, image or TextBlock with no success.
<ListBox Name="SelectL2List" ItemsSource="{Binding L2Items, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsSynchronizedWithCurrentItem="True">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<si:CallDataMethod Method="HideSelectL2View" Target="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type ViewModels:MediaItemViewModel}" >
<Border BorderThickness="1,1,3,3" Margin="10" CornerRadius="3">
<StackPanel Orientation="Horizontal" >
<Image Source="{Binding Image}"/>
<TextBlock Text="{Binding L2Title}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Any help would be appreciated.

You have to make sure that things are hit testing as well, you can set the Background of the Border to Transparent to ensure that.
Also the mouse events are intercepted by the ListBoxItems, use the tunneling versions, i.e. PreviewMouseDown.

Related

access method from template in wpf

I'm using WPF with the caliburn micro framework to implement a MVVM pattern.
I've created a popup that gets filled with custom buttons inside a ListBox.
Now I want to call a method in my ViewModel when one of these buttons is clicked, but each approach I tried so far failed.
Here the code in comments works in the sense that it calls my method, but the parameter is always null.
<ListBox x:Name="lst" ItemsSource="{Binding OperatingModes}" ItemTemplate="{DynamicResource DataTemplate_Level1}" BorderThickness="0" ScrollViewer.CanContentScroll="False" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="3" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseLeftButtonDown" >
<cal:ActionMessage MethodName="SelectMode">
<cal:Parameter Value="{Binding ElementName=lst, Path=SelectedItem}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>-->
</ListBox>
And this is the Template I'm using. Whenever I call this method, I'm getting "No target found for method SelectMode." As you can see, I've tried different aproaches, although I'm not sure that I used the TargetWithoutContext call properly.
As far as I can tell I need to somehow bind my template to the data context of the "normal" xaml code, but I failed so far. How do I access my method properly?
<DataTemplate x:Key="DataTemplate_Level1" x:Name="myListTemplate" >
<ListBox ItemsSource="{Binding}" BorderThickness="0" ScrollViewer.CanContentScroll="False" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" cal:Bind.Model="{Binding}" cal:Action.TargetWithoutContext="{Binding DataContext, ElementName=lst}">
<Button Style="{StaticResource InformButton}" Content="{Binding Path=Name}" FontSize="11" BorderBrush="BlueViolet" cal:Message.Attach="SelectMode($dataContext)">
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseRightButtonDown" >
<cal:ActionMessage MethodName="SelectMode">
<cal:Parameter Value="{Binding ElementName=myListTemplate, Path=SelectedItem.Name}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>-->
</Button>
</StackPanel>
</ListBox>
</DataTemplate>

ScrollViewer content is scrolling over other parts of window

I have the following as part of my XAML:
<DockPanel>
<ToolBar Name="toolbar1" DockPanel.Dock="Top" Height="41" Background="#FFA5D95A">
//other controls
</ToolBar>
<ScrollViewer>
<ListBox Name="listBox1" ItemsSource="{Binding ElementName=This, Path=Items}"
ItemTemplateSelector="{StaticResource entryItemTemplateSelector}">
<ListBox.Template>
<ControlTemplate>
<WrapPanel IsItemsHost="True" />
</ControlTemplate>
</ListBox.Template>
</ListBox>
</ScrollViewer>
</DockPanel>
I want the scrool bar to move the items in the ListBox just to the top of the WrapPanel, and then to stop showing them when they get to the top; in stead, these items scroll into the ToolBar at the top.
What am I doing wrong?
Note: Haing been asked, here are the DataTemplates I currently have; EntryItemHost is a type derived from WindowsFormsHost.
<DataTemplate x:Key="folderTemplate">
<my:EntryItemHost Item="{Binding}"
Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:MainWindow, AncestorLevel=1}, Path=Background}"
DoubleClick="FolderDoubleClick" />
</DataTemplate>
<DataTemplate x:Key="imageTemplate">
<my:EntryItemHost Item="{Binding}"
Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=my:MainWindow, AncestorLevel=1}, Path=Background}" />
</DataTemplate>
Instead of setting ListBox Template set the ItemsPanel and remove the ScrollViewer
sample
<DockPanel>
<ToolBar Name="toolbar1"
DockPanel.Dock="Top"
Height="41"
Background="#FFA5D95A">
//other controls
</ToolBar>
<ListBox Name="listBox1" ItemsSource="{Binding ElementName=This, Path=Items}"
ItemTemplateSelector="{StaticResource entryItemTemplateSelector}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=ContentPresenter}}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</DockPanel>
notice that I have replaced the template with ItemsPanel and restricted the width to the listbox
I made this based on the assumptions, let me know is this not what you are looking for

Scrolling of a listbox inside another listbox

I have a listbox (with normal vertical orientation), each element of which is a listbox with horizontal orientation.
I want to have a ScrollBar inside of internal listbox. So, my problem is how to set width of internal listbox according to real current width of external.
My current code is:
<Window.Resources>
<HierarchicalDataTemplate x:Key="ItemTemplateSchedule">
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem>My-Very-Long-Item-Nimber-1___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Nimber-2___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Nimber-3___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Nimber-4___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Nimber-5___</ListBoxItem>
</ListBox>
</HierarchicalDataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemTemplate="{StaticResource ItemTemplateSchedule}" >
>
</ListBox>
</Grid>
Current screenshot:
.
UPD1
Ok, answer to my question is setting of width for internal listbox, thanks to #sa_ddam213:
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}, Path=ActualWidth}"
Now I want add some new control in each row of external listbox:
<HierarchicalDataTemplate x:Key="ItemTemplateSchedule">
<StackPanel Orientation="Horizontal" Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}, Path=ActualWidth}">
<TextBlock Text="This is Text in a TextBlock"/>
<ListBox >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem>My-Very-Long-Item-Number-1___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Number-2___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Number-3___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Number-4___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Number-5___</ListBoxItem>
</ListBox>
</StackPanel>
</HierarchicalDataTemplate>
And it doesn't work now! Is it possible to solve this problem? Current screenshot:
You can use a FindAncestor to bind to the parent ListBox ActualWidth
Example:
<Window.Resources>
<HierarchicalDataTemplate x:Key="ItemTemplateSchedule">
<ListBox Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}, Path=ActualWidth}" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem>My-Very-Long-Item-Nimber-1___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Nimber-2___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Nimber-3___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Nimber-4___</ListBoxItem>
<ListBoxItem>My-Very-Long-Item-Nimber-5___</ListBoxItem>
</ListBox>
</HierarchicalDataTemplate>
</Window.Resources>
Result:

Silverlight ItemsControl vertical scrollbar, using a wrappanel as ControlTemplate

I have a collection of elements, each one with a name and a subcollection of image blobs.
I want to display an Accordion, with each item representing each of the MainElements. inside each element, I display the images in the subcollecion of said MainElement.
The Accordion gets resized by the user, so I use a wrappanel for presenting the images. When the accordion is wide enough, the images reorder themselves fitting as many as posible in each row.
the problem comes when the wrappanel only displays one image per row (because there's no space enough for more), the image list continues, but I can't see all the images, because they don't fit inside the control's height.
I need a vertical scrollbar to be displayed inside the AccordionItem so I can scroll down the image list.
So, here's my code:
<layoutToolkit:Accordion Width="Auto" Height="Auto" ItemsSource="{Binding MainElementCollection}">
<layoutToolkit:Accordion.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding MainElementName}" />
</DataTemplate>
</layoutToolkit:Accordion.ItemTemplate>
<layoutToolkit:Accordion.ContentTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding SubElementCollection}" ScrollViewer.VerticalScrollBarVisibility="Auto" >
<ItemsControl.Template>
<ControlTemplate>
<controlsToolkit:WrapPanel />
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Image Margin="2" Width="150" Source="{Binding PreviewImage, Converter={StaticResource ImageConverter}}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</layoutToolkit:Accordion.ContentTemplate>
</layoutToolkit:Accordion>
http://www.silverlightshow.net/tips/How-to-add-scrollbars-to-ItemsControl.aspx suggests that I should surround my wrappanel with a scrollviewer, like this
<ItemsControl.Template>
<ControlTemplate>
<scrollviewer>
<controlsToolkit:WrapPanel />
</scrollviewer>
</ControlTemplate>
</ItemsControl.Template>
But then my wrappanel gets really small and I can only see a small vertical scrollbar
Any ideas?
Thanks a lot.
Edit: I figured thatthe wrappanel loses its width when used in the controltemplate
It should be used as follows:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controlsToolkit:WrapPanel ScrollViewer.VerticalScrollBarVisibility="Visible" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
Anyway, I tried adding the ScrollViewer.VerticalScrollBarVisibility="Visible" line but I'm stuck again.
Edited again:
Now my wrappanel looks like this:
<ItemsControl ItemsSource="{Binding StageVideos}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controlsToolkit:WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Margin="2" Width="150" Cursor="Hand" MouseLeftButtonDown="videoPreview_MouseLeftButtonDown" Tag="{Binding}" Source="{Binding PreviewImage, Converter={StaticResource ImageConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer VerticalScrollBarVisibility="Visible">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
I'm using a wrappanel as the items panel, and I'm using the ControlTemplate to surround the presenter with a scrollviewer. Still, no luck :/
It's working perfectly. i had two different Accordions on the same page, and I was checking my code changes in the one whose code I wasn't touching.
Sometimes you need to pause, go for a walk and then look at the whole screen.
The right code is the last one:
<ItemsControl ItemsSource="{Binding StageVideos}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controlsToolkit:WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Margin="2" Width="150" Cursor="Hand" MouseLeftButtonDown="videoPreview_MouseLeftButtonDown" Tag="{Binding}" Source="{Binding PreviewImage, Converter={StaticResource ImageConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer VerticalScrollBarVisibility="Visible">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>

WPF ItemsPanelTemplate not working

I'm trying to get an ItemsPanelTemplate working for a ListBox. The ListBox is used in a DataTemplate, and none of my implicit ListBox styles override the default visual style. For some reason, the ItemsPanelTemplate I'm specifiying for the control (a WrapPanel) is being ignored and a StackPanel is used instead.
This is the entire template, I can only assume there's something I'm missing which is causing this.
<DataTemplate x:Key="GroupLargeIconsTemplate" DataType="{x:Type Core:IGroup}">
<ListBox ItemsSource="{Binding Children}" OverridesDefaultStyle="True">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Left" VerticalAlignment="Top" IsItemsHost="True" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto"
Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<conv:IconConverter x:Key="IconConverter"/>
</DataTemplate.Resources>
<StackPanel Margin="2" Width="100" Height="140">
<Image Source="{Binding Icon,Converter={StaticResource IconConverter},ConverterParameter=96}"/>
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" TextTrimming="CharacterEllipsis" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
My guess is that the width property in the WrapPanel is making it behave as a Stackpanel.
Strange, the control template is not supposed to override the explicitly specified values, rather the opposite scenario comes to my mind...
That is, unless the control template provides a panel with "IsItemsHost" set to true. Then the ItemsPanel is ignored. Which, probably, is your case.

Resources