Telerik WPF RibbonBar populated via DataBinding - wpf

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

Related

Dynamic Telerik RadOutlookBar headers come out wrong with ItemTemplate

I'm trying to use Telerik RadControls in a MVVM kind of way but having some strange problems.
The Viewmodel behind the RadOutlookBar has a collection of ViewModels that each have a Title string property. I wanted to define it so way the they get Wrapped inside a RadOutlookBarItem and bind the header/title properties together.
XAML:
<telerik:RadOutlookBar x:Name="Items">
<telerik:RadOutlookBar.TitleTemplate>
<DataTemplate>
<ContentControl Content="{Binding Path=Title}" />
</DataTemplate>
</telerik:RadOutlookBar.TitleTemplate>
<telerik:RadOutlookBar.ItemTemplate>
<DataTemplate>
<telerik:RadOutlookBarItem Header="{Binding Path=Title}" >
<ContentControl Content="{Binding}" />
</telerik:RadOutlookBarItem>
</DataTemplate>
</telerik:RadOutlookBar.ItemTemplate>
</telerik:RadOutlookBar>
This works as intended except that the Header comes out strange. Instead of being like a static string item it seems to get wrapped inside another object that behaves like a similar to a RadOutlookBarItem ( it' changes color when mouseover and such )
Even if I cahnge to straightforward string instead of binding it's still strange. But If I don't define a ItemTemplate inside the RadOutlookBar (that is, not a dynamic control) it looks all right.
What could be going on there?
Solved this and another problem in one fell swoop. I was binding to the wrong Template the whole time. This made me think I had to add OutLookBarItem myself.
In the end I was supposed to bind what I was trying to bind to the ContentTemplate.
<telerik:RadOutlookBar x:Name="Items">
<telerik:RadOutlookBar.ContentTemplate>
<DataTemplate >
<ContentControl Content="{Binding}" />
</DataTemplate>
</telerik:RadOutlookBar.ContentTemplate>
<telerik:RadOutlookBar.TitleTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</telerik:RadOutlookBar.TitleTemplate>
<telerik:RadOutlookBar.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DisplayName}" />
</DataTemplate>
</telerik:RadOutlookBar.ItemTemplate>
</telerik:RadOutlookBar>
Should work I think.

Pattern for working with a form in Silverlight 4? (How to get references to XAML elements)

I have a form:
<StackPanel Orientation="Horizontal" Visibility="{Binding Editable, Converter={StaticResource visibilityConverter}}"
ToolTipService.ToolTip="Add new topic to this group">
<sdk:AutoCompleteBox Width="160" ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.TopicNames}" />
<Button Click="addTopicButton_Click">
<Image Source="Images/appbar.add.rest.png" />
</Button>
</StackPanel>
This form appears in a DataTemplate for an ItemsControl. I'm not sure what the best way is to get the data from the AutoCompleteBox when the button is clicked. I can't give the elements x:Name attributes, because they're in a template (right?).
How can I get around this? The Click event will give me the Button, but I need a reference to the text box. Use the Button's parent, then look through the children for the Textbox? If I factored this out into its own UserControl, I could set x:Name values, but I'd rather not do that.
Any other ideas?
Update: Here is another example of such a problem:
<ListBox x:Name="topicList"
ItemsSource="{Binding Id, Converter={StaticResource topicGroupIDConverter}}"
SelectionChanged="ListBox_SelectionChanged"
HorizontalAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"
Width="150"
VerticalAlignment="Center"
ToolTipService.ToolTip="{Binding Description}"
ToolTipService.Placement="Right" />
<Button ToolTipService.ToolTip="Remove this topic from this group"
Visibility="{Binding ElementName=topicList,
Path=DataContext.Editable,
Converter={StaticResource visibilityConverter}}"
Click="removeTopicButton_Click"
HorizontalAlignment="Right"
Margin="10,0">
<Image Source="Images/appbar.cancel.rest.png" />
</Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When the button is clicked, I want to access topicList.DataContext. However, topicList itself is a DataTemplate in an ItemsControl, so I can't access it using its name from code-behind. How else can I do this?
You can add a property, say SelectedItemInAutoCompleteBox, to your presenter, and then can bind it to the SelectedItem property of AutoCompleteBox, using Mode=TwoWay, like this,
<sdk:AutoCompleteBox SelectedItem="{Binding Path=DataContext.SelectedItemInAutoCompleteBox, Mode=TwoWay}" ... />
You may try the same approach with Text property of AutoCompleteBox, also. See if it solves your problem.:-)
You have several choices:
If you're on Silverlight 5, use the AncestorBinding
Otherwise, use a Silverlight 4 AncestorBinding hack (it doesn't look pretty)
Or you could try DataContextProxy, which stores the DataContext in a resource so that it is accessible. Note: you should set the DataContextProxy as a Resource of topicList ListBox, not the UserControl as in Dan Wahlin's example.

WPF - Binding large amount of data in Listbox

I am creating a search page for books. There is lots of data in the database. If the data size is more than 2000 the application hangs. ItemsSource of the listbox having the data but something wrong is happening behind.
Code
<ListBox Grid.Column="1"
x:Name="lbResult"
ItemsSource="{Binding}"
SelectionChanged="lbResult_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Width="320">
<TextBlock Margin="10">
<InlineUIContainer>
<TextBlock Foreground="DarkKhaki" Text="{Binding Title}"/>
</InlineUIContainer>
<Run Text=" "/><LineBreak/>
<InlineUIContainer>
<TextBlock Text=" By "/>
</InlineUIContainer>
<Run Text=" "/>
<InlineUIContainer>
<TextBlock Text="{Binding Author}"/>
</InlineUIContainer>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
The application is apparently "hanging" because the data load is happening on the UI thread.
You should consider a different model that enables you to load the data in another thread and update the UI periodically or as and when new data arrives.
You can use an ObservableCollection for this.
The background loading thread updates the collection and this fires an event out to the UI thread indicating that an update is required.
There's an example of how to do this on GALA Soft
You create a property (read only in this case) for the collection:
private ObservableCollection<MyDataItem> dataItems;
public ObservableCollection<MyDataItem> DataItems
{
get { return dataItems; }
}
Then in your XAML:
<ListBox ItemsSource="{Binding ElementName=mainWindow, Path=DataItems}"
...>
</ListBox>
One problem that you may have is that you are using a non-virtualizing type of panel (WrapPanel) in your ItemsPanelTemplate. What this means is that all 2000 data items will be loaded even if only a fraction of those are visible. By default ListBox uses a VirtualizingStackPanel as its panel which, as the name indicates, provides virtualisation, so it will only load the visible data set elements.
So an easy fix in terms of performance would be to dispense with the WrapPanel and us a virtualizing panel instead, however this would obviously change the appearance.
If you particularly want a WrapPanel then there is no virtualised equivalent provided by WPF, but there are implementations out there, such as http://virtualwrappanel.codeplex.com/.
Try using a ListView instead, I had the same problem. Now I can load over 7000 items in an instant.
Like this:
<StackPanel Grid.Row="1" Grid.Column="0">
<ListView
Height="100"
Name="lstPlayerList">
<ListView.View>
<GridView>
<GridViewColumn
Width="100"
Header="LastName"
DisplayMemberBinding="{Binding LastName}">
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</StackPanel>

How can I achieve a binding path which is bound by another binding?

I'm writing my own UserControl which displays data in a ListBox. I want to achieve something similar to a property like "DisplayMemberPath". In my example, it's "EditableMemberPath", which should determine which member will be displayed in the textbox. However, using a binding on a binding does not work.
<ListBox ItemsSource="{Binding Path=Items, ElementName=me}"
SelectedItem="{Binding Path=SelectedItem, ElementName=me}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Converter={Binding Path=ItemToImageConverter, ElementName=me}}" />
<TextBlock Text="{Binding Path={Binding Path=EditableMemberPath, ElementName=me}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Can you help me finding a proper solution?
Best Regards
Oliver Hanappi
You can't do that directly in XAML (at least not with the built-in classes) : a Binding is not a DependencyObject, so you can't bind its properties.
However the post mentioned by Martin Harris looks promising...

WPF: Problem with ItemsControl datatemplate as a user control

This works fine:
<ItemsControl ItemsSource="{Binding Persons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}"/>
<TextBlock Text="{Binding Path=LastName}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
But, I want to make use of a User Control in place of the stack panel with two TextBlocks using something like:
<DataTemplate>
<jasControls:NameView/>
</DataTemplate>
But, with this and a million other syntaxes, the NameView shows nothing, yet it works fine in a separate test, outside the ItemsControl, with explicitly set (dependency) property - e.g.
<jasControls:NameView FName="{Binding Path=Person.FirstName}" />
I can find hardly any examples of this anywhere, and need to know how to specify the properties of the user control - or how can the user control 'receive' the individual item type (a Person)? What syntax to use? Do I need to specify the datatype? Is ItemsControl causing a problem or should any similar control do e.g. ListBox? Can I design it so that the user control gets an entire Person object? What dependency properties do I need in the user control? In short, how to get data into the user control?! The actual business types involved will be a bit more complicated involving some logic in the user control, hence my desire to use a user control.
ANY direction on this will be very gratefully received - TIA
Assuming your Persons collection has many Person objects in it, the DataContext property of your NameView control will automatically be set to the Person object.
You wouldn't need any dependency properties to achieve this feat. Your NameView usercontrol would simply be:
<UserControl ...>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}"/>
<TextBlock Text="{Binding LastName}"/>
</StackPanel>
</UserControl>
You should have no codebehind to get this information to display.
From there, you should be able to access the Person object from the DataContext property:
Person person = this.DataContext as Person;

Resources