TabControl with an new tab button - wpf

I have the following TabControl:
<TabControl x:Name="Networks">
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding DisplayName}" />
<Button Content="X" cal:Message.Attach="CloseItem($dataContext)" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
As you can see it is bound to a ViewModel using Caliburn.Micro, but I think this is unrelevant.
How would I add a button on to this control on the right side to add new TabItems? I'm looking for simple solution. I've searched for this but I haven't found an easy implementation of this.
Thanks

You could make the ItemsSource a CompositeCollection with a CollectionContainer for the tabs at the beginning and one explicit TabItem at the end which can add a new item on click (a +-tab as in some browsers).

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 Multiple master/details, same grid

I have a TreeView which has three levels.
Lets say its a league, division and team TreeView.
Now, when I select each of the items in the tree, I would like to see detailed information about it.
Whats the best way to achieve this?
Since Grid doesn't items (like a ListBox), I can't just set its ItemsSource and make a DataTemplate...
I thought about using a ListBox which will contain only the selected item but this seems to be very bad...
Thanks.
You first define the 3 DataTemplates for your league, division and team classes. After, you bind the TreeView to the root of your objects. Your League and Division classes should have a Children property that returns the children. All your classes should have a Name property.
Then when you want to show a single object, use the ContentPresenter, and the bind its content to the SelectedItem if the TreeView.
For example:
<StackPanel>
<StackPanel.Resources>
<DataTemplate DataType="{x:Type your_namespace:League}">
<StackPanel Orientation="Vertical">
<TextBlock Text={Binding Name}/>
<.../>
<StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type your_namespace:Division}">
<StackPanel Orientation="Vertical">
<TextBlock Text={Binding Name}/>
<.../>
<StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type your_namespace:Team}">
<StackPanel Orientation="Vertical">
<TextBlock Text={Binding Name}/>
<.../>
<StackPanel>
</DataTemplate>
</StackPanel.Resources>
<TreeView x:Name="_tree" ItemsSource="{Binding RootOfYourItems}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text={Binding Name}/>
</HierarchicalDataTemplate>
</TreeView>
<ContentPresenter Content="{Binding Path=SelectedItem, ElementName=_tree}" />
</StackPanel>
This code was not tested or compiled, it just provided as an example.
I would create a viewmodel with properties for the tree structur, the current selection and the details to the current selection.
The tree struct is one-way bound to the treeview, the SelectedItem from the treeview is OneWayToSource bound to the current selection property (due to the limitations of the property). This property changes the list of child items once the current selection changes, and the child items are bound to the listbox displaying them.

Restrict the selection a WPF TreeView With Icons to Text only

I have a simple WPF TreeView with icons
<TreeView Name="TreeViewThings" ItemsSource="{Binding}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Thing}"
ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" Margin="2">
<Image Source="Thing.png" Width="16"
Height="16"
SnapsToDevicePixels="True"/>
<TextBlock Text="{Binding Path=Name}" Margin="5,0"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
When a node is selected, the whole StackPanel is selected (both the image and the text).
How can I restrict the selection to the Text Only?
Here is a little sth I found a while ago, when I googled for sth different:
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/208805b2-225f-4da3-abd7-0d3dfa92fede/
In that thread they also talk about rewriting the TreeView. You can do so like stated in this link:http://marlongrech.wordpress.com/2008/03/15/wpf-treeview-root-node/
you don't have to rewrite the TreeView class though, simply use the xaml from the latter link. you can see how to add the controltemplate if you download the source code.

silverlight: setting RowDetailsTemplate controls from RowDetailsVisibilityChanged

Given a silverlight datagrid with RowDetailsVisibilityMode="VisibleWhenSelected", on clicking a row in the datagrid, how do you set or bind the controls in the RowDetailsVisibilityChanged() event?
<data:DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="a" x:Name="_txt" />
<ListBox x:Name="_lst"></ListBox>
</StackPanel>
</DataTemplate>
</data:DataGrid.RowDetailsTemplate>
You don't need to code the rowsvisibilitychanged event, Silverlight will do the binding for you automatically if you set up binding in your data template. Simply use {Binding col_name}.
A simplified example, binding happens automatically as user clicks a row.
<sdk:DataGrid RowDetailsVisibilityMode='VisibleWhenSelected'
ItemsSource='{Binding ElementName=ld_linkDomainDataSource, Path=Data}'>
<data:DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text='Link Name: '/>
<TextBox Text='{Binding link_name}'/> <-- column from ItemsSource
</StackPanel>
</DataTemplate>
</data:DataGrid.RowDetailsTemplate>

Resources