How do I add items dynamically to a WrapPanel? - c#

I have the following XAML:
<Window x:Class="ImageComparing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="350" Width="525" xmlns:my="clr-namespace:ImageComparing" Title="Image comparing">
<DockPanel>
<ToolBar Name="toolbar1" DockPanel.Dock="Top" Height="41" Background="#FFA5D95A">
/*other content*/
</ToolBar>
<WrapPanel Name="wrapPanel1" >
/*other content*/
<Label Content="Label" Height="28" Name="label1" />
</WrapPanel>
</DockPanel>
</Window>
I want to add content to wrapPanel1 - I tried the following code:
if (info.Attributes == FileAttributes.Directory)
wrapPanel1.Children.Add(new FolderEntry(info.Name));
else
wrapPanel1.Children.Add(new FileEntry(info.Name));
For some reason, the items don't show up. How can I fix that problem?

You should to use some ItemsControl, then add/remove the items from the item source property. You can use the ItemsPanel property or changing the template. For instance, using a ListBox and setting the Template property:
<ListBox Grid.Row="2" ItemsSource="{Binding Items}">
<ListBox.Template>
<ControlTemplate>
<WrapPanel IsItemsHost="True"/>
</ControlTemplate>
</ListBox.Template>
</ListBox>
Now when you add or remove items from the Items property in your ViewModel/DataContext the item will be showed using the WrapPanel, and not the StackPanel that is the ListBox's default.
Hope this helps...

Related

Bind an ObservableDictionary in WPF xaml file

I had an ObservableCollection<MyDataType>object named myCollection that I was presenting in a GUI using a <DataTemplate> in my .XAMLfile (See code below).
But now the type of myCollection has changed to a Dictionary<UInt64,MyDataType>.
How would I present it now? Here I found an implementation of an ObservableDictionary<>. But I don't know how I would bind this to my GUI?
Thank you for any assistance!
<Page x:Class="Project.ThisPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-ThisPage.ProjectSpace"
mc:Ignorable="d"
d:DesignHeight="480" d:DesignWidth="640"
Title="ThisPage"
Name="thisPage">
<Page.Resources>
<DataTemplate x:Key="MyDataTemplate" DataType="{x:Type local:MyDataType}">
<Label Content="{Binding Name}"/>
<Label Content="{Binding Id}"/>
</DataTemplate>
</Page.Resources>
<Grid>
<ScrollViewer>
<StackPanel>
<ItemsControl ItemsSource="{Binding ElementName=thisPage,Path=myCollection}" ItemTemplate="{StaticResource MyDataTemplate}" />
</StackPanel>
</ScrollViewer>
</Grid></Page>
myCollection.Values will give you MyDataType collection and myCollection.Keys will give you UINT64 collection. So bind to MyDataType collection just update binding like:
ItemsControl ItemsSource="{Binding ElementName=thisPage,Path=myCollection.Values}" ItemTemplate="{StaticResource MyDataTemplate}" />

How to add List item Selector to ListBox

I am currently working on Windows Phone 8 Application, i have a ListBox with TextBlock with border as a background to it, when i click on the item in the list box there is no indication to the user that he as selected that item, how to add selected item color to it?
And also i need to select multiple items in the ListBox, Which ever the item is selected its background color should be changed.
Below is my code:
<Grid x:Name="ListBoxLayout" Grid.Row="2" Margin="4,0,0,0">
<ListBox Name="listBox"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
SelectionChanged="TopicListboxSelectionChanged"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Name="AnswerCellBack" Tap="AnswerCellBack_Tap" Margin="0,0,0,4" Orientation="Horizontal">
<Border Name="borderColor" Background="#FFF2F4F7">
<TextBlock Name="text"
Width="456"
Padding="10,20,10,20"
TextAlignment="Center"
Text="{Binding Path=Value}"
Style="{StaticResource AnswerTextStyle}"/>
</Border>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
You need to use SelectionMode property to enable multiple selection in listbox.
Or you can use LongListMultiSelector from Windows Phone toolkit.
To change the background color of selected item, change the style template of listbox as mentioned here,
http://msdn.microsoft.com/en-us/library/cc278062%28v=vs.95%29.aspx.
Find this line in the ListBoxItem Style, and change it to your color
<Rectangle x:Name="fillColor2" Opacity="0" Fill="#FFBADDE9" IsHitTestVisible="False" RadiusX="1" RadiusY="1"/>
You can declare styles in App.xaml under the Application.Resources tag.
Or like these 2 ways in your page.
First Way.
<ListBox Name="lstbx">
<ListBox.Style>
// Your Style
</ListBox.Style>
</ListBox>
Second way.
Declare the styles under the tag phone:PhoneApplicationPage.Resources, like this.
<phone:PhoneApplicationPage
x:Class="Test.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d"
shell:SystemTray.IsVisible="False">
<phone:PhoneApplicationPage.Resources>
<Style x:Key="MyListStyle" TargetType="ListBoxItem">
//your style
</Style>
</phone:PhoneApplicationPage.Resources>
<ListBox Name="list1" Style="{StaticResource MyListStyle}"
//....

UserControl CollectionViewSource not working

I have a user-control containing this XAML
<UserControl x:Class="QA.JobListControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:QA" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<CollectionViewSource x:Name="itemsSource" IsSourceGrouped="True" />
</UserControl.Resources>
<ListView x:Name="JobListView" Margin="-10,-10,0,0" Padding="120,0,0,60" IsSwipeEnabled="False" ItemsSource="{Binding Source=itemsSource}" SelectionChanged="JobListView_SelectionChanged" SelectionMode="Single">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Border HorizontalAlignment="Stretch">
<TextBlock Text='{Binding Status}' Margin="10" />
</Border>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10">
<TextBlock Text='{Binding TaskName}' />
<TextBlock Text='{Binding DueDate}' />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</UserControl>
And to set the content I am using this C#-code
itemsSource.Source = Tasks.OrderBy(Tsk => Tsk.DueDate).GroupBy(Tsk => Tsk.Status);
It is showing some of the elements (but they are shown as empty elements), and not all are shown
What could be wrong?
If I am using this C#-code it is working (but it is not grouped)
JobListView.ItemsSource = Tasks.OrderBy(Tsk => Tsk.DueDate);
UPDATE
After adding the StaticResource like below, it now shows multiple groups without items
ItemsSource="{Binding Source={StaticResource itemsSource}}"
So I think you are misunderstanding the basics behind the GroupBy method. GroupBy, as opposed to most other Linq extensions, will not return a simple list of objects, instead it will return a list of IGrouping. IGrouping interface exposes a Key property which will hold the value of the grouping discriminator you passed in the GroupBy lambda.
Therefore, to get the list to display the group name, you have to bind the group header template to Key instead of Status.
<TextBlock Text='{Binding Key}' Margin="10" />
Also if reference your CollectionViewSource as a resource, you need to define a resource key to reference it later in your XAML as a StaticResource.
<CollectionViewSource x:Name="itemsSource" x:Key="groupedTasks" IsSourceGrouped="True" />
And in the list view.
<ListView x:Name="JobListView" ItemsSource="{Binding Source={StaticResource groupedTasks}}">
This way I got your example to work as expected.
As an additional read I dearly recommend you to read this article by Sergei Barskiy which demonstrates how to use grouping in XAML lists and also provides a GroupedData class that in my opinion is much better than the default IGrouping object to expose your data and consume it in the UI.

How to bind data and fill/display to DataGrid or UniformGrid from ListBox selected items (SelectionMode=Multiple)

As to my question(Title), I can already bind selected items from my listBox to my uniformGrid.
BUT even if I already selected many items the UniformGrid only shows 1 item.
Could you please tell me how to do this?
or
is it possible to fill the UniformGrid with the ListBox items selected?
or
What are the other options to transfer(bind) and show my selected items out from my ListBox?
or
I'll just go and walk through the code if you have similar examples.
To be exact, my ListBox items are images BUT doesnt need to be images only. I just want to know how to bind selected items to a Grid or anything that will display my ListBox selected items.
Thank You
XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="SampleBinding.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<StackPanel>
<Image Source="{Binding myImages}" HorizontalAlignment="Left" Height="64" Width="64"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource SampleDataSource}}">
<ListBox x:Name="listBox" HorizontalAlignment="Left" ItemTemplate="{DynamicResource ItemTemplate}" ItemsSource="{Binding Collection}" Margin="19,40,0,102" Width="200" SelectionMode="Multiple"/>
<UniformGrid x:Name="uGrid" DataContext="{Binding SelectedItem, ElementName=listBox}" Margin="273,40,78,132" d:DataContext="{Binding Collection[0]}" Grid.Row="2" Grid.Column="2">
<Image x:Name="imageItem" Source="{Binding myImages}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="100"/>
</UniformGrid>
</Grid>
I see that you bind grids DataContext to ListBox SelectedItem, which is always one. That's why you see only one item in grid. ( I guess it's always the last selected). To resolve this in more accurate MVVM way I, personally, would add a new observable collection ListBoxSelecetedItems, bind it to DataGrid, and on every ListBox selection add new selecteditem to that collection. If you unselect an item from list box, remove it from collection.
Hope this helps.

How to synchronize a TextBox with a ListBox in WPF using IsSynchronizedWithCurrentItem

I'm starting with WPF and I have this pretty easy question:
I have a TextBlock and a Listbox that share the same DataContext. The ItemsSource of the ListBox is set to point to a property of the DataContext that its an ObservableCollection. I want that the TextBlock to contain the selected item of the Listbox. Some code:
View view = new View();
view.DataContext = new ViewModel();
view.Show();
<TextBlock Name="textBox1" Grid.Row="0" Grid.Column="0" Margin="1" Text="{Binding ¿xxx?}"></TextBlock>
<ListBox Name="listBox1" Grid.Row="1" Grid.ColumnSpan="2" Margin="1" ItemsSource="{Binding Model.BinariesToDeploy}" IsSynchronizedWithCurrentItem="True" />
Hope its clear.
If you actually want to use the synchronization you need to bind to the current item of the collection which will be set by the ListBox or any other control which has IsSynchronizedWithCurrentItem set to true, to do so use the /:
<TextBlock Text="{Binding Model.BinariesToDeploy/}" />
When the source is a collection view, the current item can be specified with a slash (/). For example, the clause Path=/ sets the binding to the current item in the view. When the source is a collection, this syntax specifies the current item of the default collection view.
The current item is managed by the CollectionView which is a layer on top of your original collection, CollectionViews can also be used for filtering, sorting and grouping.
An example:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<x:Array x:Key="items" Type="{x:Type Label}">
<Label Content="Apple" Tag="Fruit"/>
<Label Content="Pear" Tag="Fruit"/>
<Label Content="Orange" Tag="Fruit"/>
<Label Content="Lime" Tag="Fruit"/>
<Label Content="Tomato" Tag="Vegetable"/>
<Label Content="Radish" Tag="Vegetable"/>
<Label Content="Lettuce" Tag="Vegetable"/>
</x:Array>
</Page.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<StackPanel>
<ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource items}}"/>
<!-- Binds to CurrentItem.Content -->
<ContentControl Content="{Binding /Content,Source={StaticResource items}}"/>
</StackPanel>
</ScrollViewer>
</Page>
try something like this
Text = "{Binding ElementName=listBox1, Path=SelectedValue.Content}"

Categories