Dynamically show a different amount (0-10) BitmapImages on a View - wpf

I have a small problem designing problem:
My card tool should display 0-10 images on my view.
Sometime just three, sometimes six, sometimes all ten...
Due to MVVM I don't want to just Controls.Add() the images to the grids/controls content.
What is a good approach to this? One way would be having ten bitmap variables, but is there another better way?
Edit:\
I tried it like that:
<ItemsControl ItemsSource="{Binding CardImages}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Stretch="Uniform" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
But its not working as it should.
I have SIX pictures, but the rest of the pictures arent visibilty (out of sigth). I want to show all of the pictures, so the 3 have to be about 50 % smaller in height and the other three atm not visible pictures should be shown under the shown three pictures. Hope thats clear.
How to solve that? I tried ScrollViewers, ViewBoxes and some different kind of templates / panels, but had no sucess. :(

I would bind an ItemsControl to a public observable collection property that contains your image sources / locations / however you reference them on your view model and then template the items to display images.
<ItemsControl Binding="{Binding MyPublicProperty}">
<ItemsControl.ItemTemplate>
<Image Source="{Binding Source={StaticResource MyImage}, Path=Source}"/>
</ItemsControl.ItemTemplate>
</ItemsControl>
See this SO question for binding the image.

Related

Binding several ItemsControl to one ObservableCollection

I have two tabs.
The code of both tabs is in the same XAML file (yes, it must be)
Each tab references the same ObservableCollection
<ItemsControl ItemsSource="{Binding ConnectorItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Depending on the tab, the collection is reloaded and contains other data
The problem is that it only displays in the last tab.
I know that this results from logical parents but I am looking for a solution in this situation
If I had a bookmark code in a separate XAML it would not be a problem but I can not use it

Listbox reversed items order

I've spend couple of hours trying to reverse the order of listbox (bottom to top) as described on the picture:
That means that newly added items should be inserted at the top of the listbox. I do not understand that something so trivial can be so difficult to implement in wpf...
I do not want to use transient effects on panel and items itself because it causes strange behavior on scrollviewer. I can not use some sort definitions on ICollectionView because I want to use a data virtualization which provides ordered data and I have to add them as is.
This is my Listbox (ListView) definition:
<ListView ItemsSource="{Binding Collection}"
VirtualizingPanel.VirtualizationMode="Recycling"
VirtualizingPanel.ScrollUnit="Pixel"
ScrollViewer.IsDeferredScrollingEnabled="True"
IsSynchronizedWithCurrentItem="True"> <!--To manage scrolling from view model using ICollectionView.ScrollTo()-->
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
<!--To auto scroll to bottom (via calling ICollectionView.ScrollToBottom()-->
<i:Interaction.Behaviors>
<Behaviors:ScrollIntoCurrentItemBehavior />
</i:Interaction.Behaviors>
<!--To pin listbox panel to bottom-->
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel VerticalAlignment="Bottom"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
Is there any acceptable solution for that? I really appreciate any help! thanks

Image binding works in Image not in ItemsControl

I am a bit baffled here. I have a List<BitmapImage> in a Viewmodel that is populating. I am trying to display the list on the view with an ItemsControl, but the Images don't show up. Oddly, I can access the same collection and get an image to display if I am using an Image tag.
<ItemsControl ItemsSource="{Binding Path=Images}" MinHeight="80">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" MinWidth="80" MinHeight="80" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Image HorizontalAlignment="Left" Name="image1" Stretch="Uniform" VerticalAlignment="Top" Source="{Binding Path=Images[0]}" MinHeight="80" MaxHeight="200" />
Note that they both point to Images. The Image shows up, the ItemsControl stays empty. What is going on?
You'll solve this by using an ObservableCollection as opposed to a List. The ItemsControl isn't going to rebind on the change notification of a List. You won't have to worry about explicitly calling the change notification for the List either if you use an ObservableCollection.
I was able to replicate your scenario and simply using an ObservableCollection solves the issue. As to why: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
Specifically, see this quote in the Remarks section:
For change notification to occur in a binding between a bound client and a data source, your bound type should either: Implement the INotifyPropertyChanged interface (preferred). Provide a change event for each property of the bound type. Do not do both.

WPF Listbox Wrapping

I have a listbox in which I use a ListBox.ItemsPanel - WrapPanel.
<ListBox ItemsSource="{Binding Path=Applets}" Margin="10,92,10,10" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" IsItemsHost="True">
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>...
I am trying to have the wrappanel have a behavior such that the items fill in to the right as the width is made wider and wrap as needed when the window is made narrower. I have played with it but the correct combination eludes me. Does anyone have a suggestion?
My next goal would be able to reorder/ sort the items and have the render update.
TIA
I am trying to have the wrappanel have a behavior such that the items fill in to the right as the width is made wider and wrap as needed when the window is made narrower. I have played with it but the correct combination eludes me. Does anyone have a suggestion?
The code you have is almost correct, just change the Orientation to Horizontal and it should work as you describe
My next goal would be able to reorder/ sort the items and have the render update.
You don't have to do anything special for that, it's the normal behavior of a ListBox. Just change the sort order (using ICollectionView.SortDescriptions), and the UI will reflect the changes
<ListBox Grid.Row="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBoxItem Name="lbiTmp3_1"><CheckBox>
<TextBlock TextWrapping="Wrap">
lkjfd gmlkdsfmlk gmdsgf kds lkjglfdjmlkg jfdsg dsgf lkhfdgs lkjds fg
</TextBlock></CheckBox>
</ListBoxItem>
<ListBoxItem Name="lbiTmp3_2">C0ucou</ListBoxItem>
<ListBoxItem Name="lbiTmp3_3">C0ucou</ListBoxItem>
</ListBox>

How to bind a Canvas to a collection of items in Silverlight

Background
I've got a collection of objects which I want to draw on a canvas. Each of these object has a DateTime property, which determines the position of that object along the x-axis on the canvas. Each object also has some other properties which determine the image that need to be drawn on the canvas. The most important feature that I want to implement is that as time passes by the second, these images representing the objects would move along the x-axis. In other words, the right vertical boundary of the canvas would always represent the current time (e.g. DateTime.Now), and objects in the collection would need to update their position on the canvas relative to that boundary. I am very new to Silverlight and hence I have quite a few questions including the following. In addition, I also have the requirement to follow the MVVM framework.
Questions
What should I use in the XAML to achive the above? I thought about using ItemsControl with Canvas as the Panel, but I am not sure how to do it or even whether it is the best way. Any actual XAML code would be great.
How should I bind the collection of objects to the canvas? And if so, how do I move them along the x-axis as time passes? That is, I would like the canvas to update whenever:
there are objects added to the
collection; or
objects removed from the collection;
or
existing object changing (e.g. some
property changed and hence need to
change the image that get shown on
the canvas) in the collection; or
even if there are no changes to the
collection as mentioned above, these
objects will need to move every
second.
Sorry if I have use the wrong terms for anything as I am still new to Silverlight.
Thanks.
I know this question is a little old, but you can just use a render transform - I'm doing something similar;
<ItemsControl ItemsSource="{Binding Notes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="{Binding W}" Height="{Binding H}" BorderBrush="Navy" BorderThickness="5" CornerRadius="10">
<TextBlock Text="{Binding Text}"/>
<Border.RenderTransform>
<TransformGroup>
<... elided ...>
<TranslateTransform X="{Binding X}" Y="{Binding Y}"/>
</TransformGroup>
</Border.RenderTransform>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you really want to use MVVM and data-binding, then an ItemsControl with the ItemsPanel defined as a Canvas might just work. Bind the ItemsControl.ItemsSource to an ObservableCollection in your VM. In your ItemTemplate for the ItemsControl, bind the UI item element's Canvas.X and Canvas.Y to your data items, using an IValueConverter in between to do the mapping of DateTime to X coord, etc...
Something like this:
<ItemsControl ItemsSource="{Binding Path=MyItemsInVM, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas></Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Width="50" Height="50" Canvas.Left="{Binding Path=MyDateTimeProperty, Converter={StaticResource DateTimeToLeftOffsetConverter}}" Canvas.Top="100" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Another approach is using the Model-View-Presenter pattern. MVVM is not the only show in town. When you have the need to do a lot of UI manipulation, or work with the VSM, then a Presenter can be a better fit (although Behaviors can also play an important role).
You can set up a timer in your presenter that operates at your refresh interval, and in the Presenter just handle the timer event to iterate over the collection and map objects to (X,Y) positions, updating the UI elements directly.

Resources