Getting ScrollViewer.VerticalOffset from ListBox in PivotControl - silverlight

I have a PivotControl that contains ListBox elements:
<controls:Pivot Title="SECTIONS" x:Name="pivotControl" ItemsSource="{Binding SectionViewModels}">
<controls:Pivot.HeaderTemplate>
<!-- -->
</controls:Pivot.HeaderTemplate>
<controls:Pivot.ItemTemplate>
<DataTemplate>
<StackPanel>
<!-- if you don't explicitly specify the height, the scrolling won't work -->
<ListBox ItemsSource="{Binding StoryViewModels}" SelectionChanged="StoryList_SelectionChanged"
Height="625" u:ScrollViewerMonitor.AtEndCommand="{Binding ElementName=LayoutRoot, Path=DataContext.FetchMoreDataCommand}">
<ListBox.ItemTemplate>
<DataTemplate>
<local:StoryControl />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</controls:Pivot.ItemTemplate>
</controls:Pivot>
I want to get and set the ScrollViewer.VerticalOffset of a ListBox corresponding to a given SectionViewModel (which is the item source of the pivot control). How can I do this?

There're some cases that you need to access view elements. For those cases using the VisualTreeHelper is the solution. You can find a summary of it in my blog and some helper extension methods.
I recommend to use SilverlightSpy to see how the VisualTree is composed at runtime and be able to more efficiently navigate it.

Related

Adding a small popup on a wpf listbox that is already using itemsource

Here is a portion of my wpf-xaml code :
<ListBox x:Name="TestJobSuiteListBox" Grid.Row="1" ItemsSource="{Binding AvailableJobs}" MouseRightButtonDown="TestJobSuiteListBox_OnMouseRightButtonDown">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<ListBoxItem Content="{Binding Name}"/>
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I would like to add another listboxitem to that ListBox and I dont want it to be visible before you rightclick on the listbox. It also should not be bound to the "AvailableJobs" property.
Something like this :
<ListBox x:Name="TestJobSuiteListBox" Grid.Row="1" ItemsSource="{Binding AvailableJobs}" MouseRightButtonDown="TestJobSuiteListBox_OnMouseRightButtonDown">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<ListBoxItem Content="{Binding Name}"/>
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
<ListBoxItem x:Name="AddJobbListBoxItem" Visibility="Hidden"></ListBoxItem>
</ListBox>
This doesn't work, because of "itemsource must be empty problem"
Anyone have a good Idea of how I could do it ?
I don't need help with the visibility/rightclick functionality.
Thanks in advance, I hope the problem is understandable.
You can put listbox to stackPanel, and disable it's scrolling. Then add that one element also to the stackPanel under the listbox, and finally add that stackPanel to scrollViewer. Then you have listbox with AddButton.
<ScrollViewer>
<StackPanel>
<ListBox ItemsSource="{Binding AvailableJobs}"
ScrollViewer.VerticalScrollBarVisibility="Disabled">
<!-- ... -->
</ListBox>
<Button x:Name="AddJobbButton" Visibility="Collapsed" />
</StackPanel>
</ScrollViewer>
Notice that if you have lots of items in listbox, there might be some performance problems, because I'm not sure that listbox's virtualizing is working correctly if it's in stackPanel.
EDIT: of course you have to listen mouse events and set then button's visibility to visible and so on...
I think you have to use ItemTemplateSelector to achieve this functionality. You can create different DataTemplate as per your requirement in the Resources section and bind properly in the xaml. Check the answer here, it will give you the idea about the approach. Please refer this examlpe also. Hope this will help.

How can I bind Image control to ListBox dynamically?

I want to implement a ListBox which each item include a Image control and some other controls, then use it to binding some data. Due to this ListBox need to contains more than 2000 items, this means I have to do some optimization for it.
First, I noticed that most of the Image controls has one same picture(Default avatar), so I create a singleton ImageSource-object for the data. But although the Image control's source is the same object, you know I also need to create 2000 Image control in the ListBox with DataTemplate below:
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Avatar}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Is there have a way to reduce Image control object's number in my program? Thank you!

wpf grid with dynamic columns

I have a collection that I wish to bind to a WPF grid.
The problem I'm facing is that the number of columns is dynamic and is dependent on a collection. Here is a simple mock up:
public interface IRows
{
string Message{get;}
IColumns[] Columns{get;}
}
public interface IColumns
{
string Header {get;}
AcknowledgementState AcknowledgementState{get;}
}
public interface IViewModel
{
ObservableCollection<IRows> Rows {get;}
}
I want my view to bind to the the Rows collection, which contains a collection of Columns.
My Columns collection contains an enum which should be represented by an image (1 of 3 possibilities). It also contains a Message property which should only be displayed in one column (static and is just some text information). It also contains a Header string which should be displayed as a header for that column.
Note that the number of columns is variable (at the moment the headers are set to Acknowledge but this will change to represent dynamic data).
Update: This is after implementing suggestions from Rachel
<ItemsControl
ItemsSource="{Binding Items, Converter={StaticResource PresentationConverter}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid ShowGridLines="true"
local:GridHelpers.RowCount="{Binding RowCount}"
local:GridHelpers.ColumnCount="{Binding ColumnCount}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding RowIndex}"/>
<Setter Property="Grid.Column" Value="{Binding ColumnIndex}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type UI:MessageEntity}">
<TextBox Text="{Binding Message}"></TextBox>
</DataTemplate>
<DataTemplate DataType="{x:Type UI:StateEntity}">
<TextBox Text="{Binding State}"></TextBox>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This almost gives me what I want now. I'm only stuck with what I should do for the headers.
Any suggestions are welcome.
You can use nested ItemsControls for this
Here's a basic example:
<!-- Bind Rows using the default StackPanel for the ItemsPanel -->
<ItemsControl ItemsSource="{Binding Rows}">
<!-- Set the Template for each row to a TextBlock and another ItemsControl -->
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!-- Need to set Width of name TextBlock so items line up correctly -->
<TextBlock Width="200" Text="{Binding Name}" />
<ItemsControl ItemsSource="{Binding Columns}">
<!-- Use a horizontal StackPanel to display columns -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Using a grid approach might make things more complicated than they should be. Have you tried changing the template of a listview, or to use the DataGrid instead for this purpose?
For an example, take a look at this project: http://www.codeproject.com/Articles/25058/ListView-Layout-Manager
Or this one: http://www.codeproject.com/Articles/16009/A-Much-Easier-to-Use-ListView
If you go with the Grid, I believe you'll have to add a lot of code behind to manage the amount of columns and rows, their size, the cell content... Whereas a ListView/DataGrid will let you do this dynamically through Templates.
Create a Grid using code as shown at http://msdn.microsoft.com/en-us/library/system.windows.controls.grid(v=vs.90).aspx#feedback
create a property of type ColumnDefinition,( and use property changed ) to create columns.
There is also the option of using a dynamic object to create your columns. This is a bit laborious but the results are very effective and the solution in general is quite flexible.
This will show you the basics to the dynamic object
Binding DynamicObject to a DataGrid with automatic column generation?
I had some trouble using it with nested objects, columns that have objects and then trying to bind cell content to the object.
Here's a question I raised with an example of how to do this
Problems binding to a the content of a WPF DataGridCell in XAML

WPF Implicit selection of template using DataTemplate, but outside of 'List'

In my project, I have TreeView, which contains a tree of objects of various types (all subclassed from the same superclass).
To the right of my TreeView I would like to have a "panel" (at the moment I just have a Grid) which displays information about the object currently selected in the tree. I want to use DataTemplate, as in the second example on this page, to adapt the layout & content of my "panel" based on the subclass type; however, I cannot find a suitable container (as I don't want a list control - I want to change my display for one item based on the selection in the treeview).
This question asks the same thing but I don't think the answer is suitable for me because I want the template to change dynamically depending on the type.
I.e. I was hoping for something like:
<[A Suitable Container] Margin="189,39,12,12" DataContext="{Binding ElementName=treeView1, Path=SelectedItem}">
<DataTemplate DataType="{x:Type local:subclass1}">
<Grid>
<!-- subclass1 specific stuff -->
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:subclass2}">
<Grid>
<!-- subclass2 specific stuff -->
</Grid>
</DataTemplate>
</[A Suitable Container]>
Use a ContentControl
<ContentControl Content="{Binding ElementName=treeView1, Path=SelectedItem}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type local:ViewModelA}">
<local:ViewA />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ViewModelB}">
<local:ViewB />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>

Telerik WPF RibbonBar populated via DataBinding

I have and object model, a UserProfile, that contains many ServiceProfile, each containing many CommandProfile.
I have bound this model with Telerik WPF OutlookBar:
<telerikNavigation:RadOutlookBar
ItemsSource="{Binding ServiceProfiles}"
Background="{Binding Color}">
<telerikNavigation:RadOutlookBar.TitleTemplate>
<DataTemplate>
<Label Content="{Binding Description}"/>
</DataTemplate>
</telerikNavigation:RadOutlookBar.TitleTemplate>
<telerikNavigation:RadOutlookBar.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Description}"/>
</DataTemplate>
</telerikNavigation:RadOutlookBar.ItemTemplate>
<telerikNavigation:RadOutlookBar.ContentTemplate>
<DataTemplate>
<ListBox ItemsSource="{Binding CommandProfiles}" Background="Transparent">
<ListBox.ItemTemplate>
<DataTemplate>
<Button
Content="{Binding Description}"
Command="{Binding ExecuteCommand}"
/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DataTemplate>
</telerikNavigation:RadOutlookBar.ContentTemplate>
</telerikNavigation:RadOutlookBar>
This XAML code creates a OutlookbarItem for each ServiceProfile. Each OutlookbarItem presents a list of buttons as a content.
I'm not able to do the analogous job with ribbonBar: inside a single tab (referring to my UserProfile), I want to create a RibbonGroup for each ServiceProfile. Inside each Group (Service profile) there are many Ribbonbuttons, one for each CommandProfile.
But I'm not able.
I arrive to this code:
<telerikRibbonBar:RadRibbonTab
x:Name="theTab"
Header="{Binding Description}"
Background="{Binding Color}"
ItemsSource="{Binding ServiceProfiles}">
</telerikRibbonBar:RadRibbonTab>
which creates the ribbongroups, but I'm not able to control anything (title of the group, fill (via Binding) the content.
Any idea?
Thanks
Marco Parenzan
Bit late, but sorry to say but it doesn't look supported yet:
http://www.telerik.com/community/forums/silverlight/ribbonbar/headertemplate-of-radribbontab.aspx
Hello Alex Fan,
Unfortunately the RibbonBar doesn't support databinding for now. However, you can put your vote for this feature in our PITS thus increasing its priority.
In your case the best will be if you add the ribbon items programmatically.
Let us know if you need more info.
All the best,
Tina Stancheva
the Telerik team

Resources