SelectedItem in XAML CollectionViewSource - c#

Im trying to use SelectedItem in my Xaml and display som of its properties. Here is the view:
<UserControl.Resources>
<CollectionViewSource x:Name="cvs"
IsSourceGrouped="True"
Source="{Binding Path=GroupedPeople}"
ItemsPath="Items"/>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<ScrollViewer
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Grid Grid.Row="0" Background="DarkSeaGreen">
<GridView x:Name="myGridView">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Left" />
<Setter Property="Padding"
Value="5" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key}"
FontSize="26.67" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" ItemWidth="220" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ItemsControl.GroupStyle>
</GridView>
</Grid>
</ScrollViewer>
<Grid HorizontalAlignment="Left" Height="177" Margin="708,37,0,0" Grid.Row="1" VerticalAlignment="Top" Width="558">
<TextBlock Text="{Binding SelectedPerson.Name}"></TextBlock>
</Grid>
As you can see its at the bottom-grid I would like to display the SelectedItem.
There seem to be a problem using SelectedItem with at CSV, for example I cannot do:
<CollectionViewSource x:Name="cvs"
IsSourceGrouped="True"
Source="{Binding Path=GroupedPeople}"
ItemsPath="Items"
SelectedItem="{Binding SelectedPerson}"/>
Beacuse SelectedItem will not work here.
I have this method in my code:
private Person _selectedPerson;
public Person SelectedPerson
{
get { return _selectedPerson; }
set
{
_selectedPerson = value;
RaisePropertyChanged("SelectedPerson");
}
}
But it never seems to get hit.
Help appreciated. Thank you!

Related

XAML : expand expander when an item in the group is selected

Is it possible for a expander to check for the IsExpanded Property if an item inside the group of the expander is selected then this expander is expanded so IsExpanded will be true? Because if i set it to true by default all expanders will be expanded at that's not the goal.
<controls:CommandListBox Grid.IsSharedSizeScope="True"
Visibility="{Binding IsComponentOrSystemPropertySearch, Converter={StaticResource BooleanToVisibilityConverter}}"
Grid.Column="2"
HorizontalAlignment="Stretch"
SelectedItem="{Binding SelectedResult}"
ToolbarItems="{Binding ToolBarItems}"
ItemsSource="{Binding SearchResults, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.Resources>
<ResourceDictionary>
<Style x:Key="GroupHeaderStyle"
TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="exp" IsExpanded="False" Margin="0,0,0,30" >
<Expander.Header >
<TextBlock Text="{Binding Path=Name}" FontSize="18" Padding="0" Margin="0"/>
</Expander.Header>
<Grid Margin="20 0 0 0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentPresenter Grid.Column="0"
Grid.Row="0"
Content="{Binding Path=Items[0].DisplayRepresentation.Header}"/>
<ItemsPresenter Grid.Column="0"
Grid.Row="1"/>
</Grid>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</ItemsControl.Resources>
<ItemsControl.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ItemsControl.GroupStyle>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:DeluxePropertySearchResult}">
<ContentPresenter Content="{Binding DisplayRepresentation}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</controls:CommandListBox>

How do I add a Label over a ListBox in WPF?

I have currently a ListBox in a DockPanel (that represents a wonderful Diaballik game) and at the end I want to be able to show up a label Victory over the grid made by the boxes like in the picture :
<DockPanel>
<ListBox DockPanel.Dock="Top" ItemsSource="{Binding Cases}" SelectedItem="{Binding SelectedCase, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Top" SnapsToDevicePixels="True">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding Size}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Ellipse Fill="{Binding Color}" Width="50" Height="50" Visibility="{Binding HasPawn, Converter={StaticResource bool2visibility}}"/>
...
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Label Content="VICTORY" /> <!-- How can this go over the list box ? -->
</DockPanel>
You could do something like this (the behaviour of a Grid is such that it will just "stack" the items "on top" of each other):
<DockPanel>
<Grid DockPanel.Dock="Top">
<ListBox ItemsSource="{Binding Cases}" SelectedItem="{Binding SelectedCase, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Top" SnapsToDevicePixels="True">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding Size}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid >
<Ellipse Fill="{Binding Color}" Width="50" Height="50" Visibility="{Binding HasPawn, Converter={StaticResource bool2visibility}}"/>
...
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Label Content="VICTORY" HorizontalAlignment="Center" VerticalAlignment="Center" /> <!-- How can this go over the list box ? -->
</Grid>
</DockPanel>

Why are ListView and grouped CollectionViewSource not showing any items?

Here is code (minified):
<Page
x:Class="Compote.HubPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Compote"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding HubViewModel, Source={StaticResource Locator}}"
mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<DataTemplate x:Key="DefaultItemTemplate">
<Border Margin="0,0,0,9.5" Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Grid>
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" Height="170"/>
<StackPanel Margin="15,12" VerticalAlignment="Bottom">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="14.5" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="{Binding Name}" Style="{ThemeResource CustomListViewItemTextBlockStyle}" />
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding Price, Converter={StaticResource PriceConverter}}" Style="{ThemeResource CustomListViewItemSecondaryTextBlockStyle}"/>
</Grid>
<TextBlock Text="{Binding Description}" Style="{ThemeResource ListViewItemContentTextBlockStyle}" TextTrimming="CharacterEllipsis" />
<TextBlock Text="{Binding Weight, Converter={StaticResource WeightConverter}}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" />
</StackPanel>
</Grid>
</Border>
</DataTemplate>
<CollectionViewSource x:Key="CollectionViewSourceCategories" Source="{Binding Categories}" IsSourceGrouped="True" ItemsPath="Items" />
</Page.Resources>
<ListView AutomationProperties.AutomationId="ItemListViewSection4"
AutomationProperties.Name="Items In Group"
SelectionMode="None"
IsItemClickEnabled="True"
ItemsSource="{Binding Source={StaticResource CollectionViewSourceCategories}}"
ContinuumNavigationTransitionInfo.ExitElementContainer="True"
ItemTemplate="{StaticResource DefaultItemTemplate}" AllowDrop="True">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
As you can see, the CollectionViewSource is binded to the ListView and its IsSourceGrouped property is set to True. Categories contains 2 categories with 3 items in each category. But the ListView doesn't show anything, it's totally empty. What's wrong?
you need to add an itemPresenter in the GroupStyle.
<ListView Name="MyList" ItemsSource="{Binding Source={StaticResource CollectionViewSourceCategories}}" Grid.Row="1" Grid.Column="0">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<!-- ItemsPresenter -->
<ItemsPresenter />
<TextBlock Text="{Binding Name}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="NAME" DisplayMemberBinding="{Binding name}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Something else that might be helpful if you're grouping items Is to add a PropertyGroupDescription to your collectionViewSource:
First add this to your declarations:
xmlns:dat="clr-namespace:System.Windows.Data;assembly=PresentationFramework" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
then your CollectionViewSource:
<CollectionViewSource x:Key="CollectionViewSourceCategories" Source="{Binding Categories}">
<CollectionViewSource.GroupDescriptions>
<dat:PropertyGroupDescription PropertyName="Categories" />
</CollectionViewSource.GroupDescriptions>
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Names" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
This will group by your category, then sort by names. here's the link explaining it:
https://msdn.microsoft.com/en-us/library/ff407126(v=vs.100).aspx
hope this helps!
You have to bind to the View property of the CollectionViewSource:
ItemsSource="{Binding Source={StaticResource CollectionViewSourceCategories}, Path=View}"

Overlay multiple rectangles on a resized image

I'm new to WPF and I'm trying to visualize images with rectangles drawn over the faces in each image.
I have information about the width, height, top left X and Y co-ordinates (in pixels wrt the original image) of each rectangle in each image.
My C#:
public class FaceRectangle
{
Rectangle rect;
public FaceRectangle(int topX, int topY, int width, int height)
{
rect = new Rectangle(topX, topY, width, height);
}
public int X { get { return rect.X; } }
public int Y { get { return rect.Y; } }
public int Width { get { return rect.Width; } }
public int Height { get { return rect.Height; } }
...
}
public class Photo
{
public BitmapImage Img { get; set; }
public string Filename { get; private set; }
public ObservableCollection<FaceRectangle> Faces { get; private set; }
...
}
public class PhotoCollection : ObservableCollection<Photo>
{
...
}
After looking through related questions, this is the XAML I have - but I'm having trouble overlaying the rectangles on the image and adjusting their size and posiiton to match the image. How should I go about achieving this?
UPDATED XAML
<Window x:Class="TempFaceViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:er="clr-namespace:TempFaceViewer"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=System">
<Window.Resources>
<Style TargetType="{x:Type ListBoxItem}" x:Key="ImageListItem">
<Style.Resources>
<!-- Background of selected item when focussed -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Gray" />
</Style.Resources>
</Style>
<!-- Main photo catalog view -->
<Style TargetType="{x:Type ListBox}" x:Key="PhotoListBoxStyle">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}" >
<WrapPanel Margin="5" IsItemsHost="True" Orientation="Horizontal"
ItemHeight="95"
ItemWidth="95"
VerticalAlignment="Top" HorizontalAlignment="Stretch" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Image Template -->
<DataTemplate DataType="{x:Type er:Photo}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Margin="6">
<!-- Drop Shadow -->
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="4" Background="#44000000">
<Border.RenderTransform>
<TranslateTransform X="5" Y="5" />
</Border.RenderTransform>
<Border.BitmapEffect>
<BlurBitmapEffect Radius="8" />
</Border.BitmapEffect>
</Border>
<!-- Image Template -->
<Border Padding="4" Background="White" BorderBrush="#22000000" BorderThickness="1">
<Image Source="{Binding Img}" />
</Border>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource Photos}}">
<Grid.RowDefinitions>
<RowDefinition Height="100*" />
<RowDefinition Height="100*" />
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.Row="0" Margin="0,0,0,10" Height="160">
<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
<ListBox
IsSynchronizedWithCurrentItem="True"
Name="PhotosListBox"
Style="{StaticResource PhotoListBoxStyle}"
Margin="5"
SelectionMode="Extended"
ItemsSource="{Binding}"
SelectedIndex="0"
ItemContainerStyle="{StaticResource ImageListItem}"
>
</ListBox>
</ScrollViewer>
</DockPanel>
<Viewbox Grid.Column="0" Grid.Row="1">
<Grid>
<Image Source="{Binding Img}" />
<ItemsControl ItemsSource="{Binding Faces}" HorizontalAlignment="Left" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="er:FaceRectangle">
<Rectangle Width="{Binding Width}" Height="{Binding Height}" Stroke="Red" StrokeThickness="1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
</Viewbox>
</Grid>
</Window>
Thanks!
Set your canvas top/left properties in ItemContainerStyle instead and put both the background image and the ItemsControl in a Grid so that they're overlapping, aligned and using the same scale (pixels). If you wrap this grid in a ViewBox then everything will scale together as needed:
<Viewbox>
<Grid>
<Image Source="{Binding Img}" />
<ItemsControl ItemsSource="{Binding Faces}" HorizontalAlignment="Left" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="er:FaceRectangle">
<Rectangle Width="{Binding Width}" Height="{Binding Height}" Stroke="Red" StrokeThickness="1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
</Viewbox>
UPDATE: You'll have to post any other code on the page. I've tried putting it in a grid as you describe and it works fine, there's nothing else in my window other than this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100*" />
<RowDefinition Height="100*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100*" />
<ColumnDefinition Width="100*" />
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="0" Grid.Row="1">
<Grid>
<Image Source="{Binding Img}" />
<ItemsControl ItemsSource="{Binding Faces}" HorizontalAlignment="Left" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="er:FaceRectangle">
<Rectangle Width="{Binding Width}" Height="{Binding Height}" Stroke="Red" StrokeThickness="1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
</Viewbox>
</Grid>
I suspect you've got resources elsewhere (i.e. Styles, DataTemplates etc) that are changing the default behavior, trying running my code in an isolated app.

Vertical align listbox to bottom

I need to layout my listbox like on this picture
I have tried everything to do that both for listbox and longlistselector..
<ListBox WP7Panels:DockPanel.Dock="Bottom" Name="MsgControlsList"
ItemsSource="{Binding}"
Height="600"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Bottom" VerticalContentAlignment="Bottom">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="VerticalAlignment"
Value="Bottom" />
<Setter Property="VerticalContentAlignment"
Value="Bottom" />
</Style>
</ListBox.Style>
<ListBox.ItemTemplate>
<DataTemplate>
<WP7Panels:DockPanel LastChildFill="True">
<HistoryClasses:HistoryElementTemplate WP7Panels:DockPanel.Dock="Bottom" VerticalAlignment="Bottom" DataContext="{Binding}" HorizontalContentAlignment="Stretch"/>
</WP7Panels:DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</WP7Panels:DockPanel>
..but still I have top vertical alignment of the listbox.
Any thoughts, please?
If you don't set the height of your listbox the items are on the bottom of the screen.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="600"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Test"/>
<ListBox Grid.Row="1" VerticalAlignment="Bottom">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="Item"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Grid.Row="2" Text="Test"/>
</Grid>

Categories