WPF Display ListView in tabs of TabControl with different content - wpf

I am trying to display a WPF ListView in a tab of TabControl. I am trying to achieve the following: if I click on a button, a new TabItem should be created and in that TabItem a ListView should be shown with its own content.
So if I click on another button, a new tab item should be created and the ListView in this second tab item should display another content.
I am setting the DataContext to display items in the list view. The lines in the list view are displayed like this:
XAML:
<GridViewColumn Width="1500">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding myLine}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
The listview is displayed like this:
<TabControl x:Name="tabControl" Grid.Column="2" HorizontalAlignment="Left" Height="372" Margin="10,32,0,0" VerticalAlignment="Top" Width="894">
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:MyTab}">
<TextBlock Text="{Binding _header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type local:MyTab}">
<ListView x:Name="myListView" ...></ListView>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
How can I display various tabs with their own content?

You will have to bind your list of tabs from your DataContext to TabControl.ItemsSource.
<TabControl ItemsSource="{Binding Tabs}"/>
And on your DataContext have a property called Tabs that is a list or collection of your datatypes;
public IList<MyTab> Tabs { get; private set; }

Related

TabControl with an new tab button

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).

Update items in ComboBox after lookup value is added

I have a WPF form that contains a DataGrid. This DataGrid is editable. One column of the DataGrid contains a ComboBox with a list of lookup codes for the user to select from.
While editing, the user can add a new lookup code by calling a modal window. When control is returned to the DataGrid, the combobox does not have the new lookupcode.
How can I refresh the list in the combobox after an item is added?
Here is how my combobox is defined. Below is the column of the DataGrid and then my dictionary snippet.
<DataGridTemplateColumn Header="Type" Width="160">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding AddrType.Description}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox Name="cboAddrtype"
ItemsSource="{Binding Source={StaticResource addrTypeList}}"
SelectedValuePath="ID"
DisplayMemberPath="Description"
SelectedValue="{Binding AddrTypeID, UpdateSourceTrigger=PropertyChanged}"
Width="100" />
<Button ToolTip="New" Name="btnNewAddressType" Click="btnNewAddressType_Click">
<Image Source="Images\Add.png" Style="{StaticResource buttonImageStyle}" />
</Button>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
The method GetAddressTypes() returns an ObservableCollection.
<ObjectDataProvider x:Key="addrTypeList" IsAsynchronous="True"
MethodName="GetAddressTypes"
ObjectType="{x:Type components:AddressComponent}"/>
I would add the new address to the addrtypeList when the modal window is closed, or the object saved depending on your desired behavior. Because its an observableCollection it should update the combo box automatically.

Databinding and bound buttons

I have an ItemsControl bound to a list of objects.
It basically displays a list of bound properties on screen with a textbox and button next to each one to allow you to add additional information to each database field.
In the onclick of the button I need to take the string in the textbox and store it in the object for that item. The XAML looks a bit like this
<ItemsControl x:Name="ListDatabaseFields" ItemsSource="{Binding Path=SelectedImport.ColumnMappings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel>
<TextBlock Text="{Binding DatabaseColumn.Name}" TextWrapping="Wrap" Grid.Column="0"/>
<TextBox Name="txtNewFileField" Width="100"/>
<Button Name="Add" Content="Add File Field" Style="{StaticResource LinkButton}" Width="50" Click="Add_Click"/>
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Whats the best way in the XAML to access the ColumnMapping the itemcontrol is bound to for that item and change its file field property.
I'm not sure if i understood your question correctly, please clarify if this is not what you are looking for.
I have adapted this to my test application, my DataTemplate looks like this:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<TextBox MinWidth="100" Name="tbNewName"/>
<Button MinWidth="100"
Tag="{x:Reference tbNewName}" Click="ButtonNewName_Click"
Content="Do Stuff"/>
</StackPanel>
</DataTemplate>
Notice the Button.Tag which references the TextBox, i can use it in the handler like this:
private void ButtonNewName_Click(object sender, RoutedEventArgs e)
{
Employee emp = (sender as FrameworkElement).DataContext as Employee;
TextBox tbNewName = (sender as FrameworkElement).Tag as TextBox;
emp.Name = tbNewName.Text;
}
The DataContext is inherited, so the sender (the Button) contains the data-item, in your case a ColumnMapping, the Tag gives me the TextBox and that is all i need for changing a property.
If you need to reference more controls you could create an array in the Tag.

Silverlight: How to dynamically bind a ComboBox in a ListBox ItemTemplate?

I have a list box that requires at least one ComboBox. I couldn't find a way to place the ComboBox in the ItemTemplate I use.
...
<DataTemplate x:Key="parts_template">
<StackPanel Orientation="Horizontal">
<TextBlock .../>
<ComboBox .../>
</StackPanel>
</DataTemplate>
...
<ListBox x:Name="lb_parts" ItemTemplate="{StaticResource parts_template}" .../>
...
How do bind that ComoBox in the DataTemplate to an ObservableCollection in the code behind?
Another thing you could try is subscribe the Loaded event on the ComboBox.
Then you can set the ComboBox.ItemsSource in the EventHandler to MyObservableCollection.
Have a look
XAML:
<DataTemplate x:Key="parts_template">
<StackPanel Orientation="Horizontal">
<TextBlock .../>
<ComboBox Loaded="ComboBox_OnLoaded">
<!-- ComboBox ItemTemplate -->
</ComboBox>
</StackPanel>
</DataTemplate>
C# Code Behind:
private void ComboBox_OnLoaded(object sender, EventArgs e)
{
((ComboBox)sender).ItemsSource = MyObservableCollection;
}
Okay, here is how you can add a ComboBox to the ListBox in the code behind.
Create a ComboBox
ComboBox x = new ComboBox();
If you have a data source that populates the ComboBox then you can just bind that
x.ItemsSource = e.Result;
If you do not and want to manually add items to the ComboBox:
ComboBoxItem y = new ComboBoxItem();
Set the Content of the Item to what you want displayed in the ComboBox
y.Content = "Hello";
Now all that is left, is to add the ComboBoxItem to the ComboBox (only if you are creating the Items manually), and then the ComboBox to the ListBox
x.Items.Add(y);
//testing is my ListBox
testing.Items.Add(x);
You should be able to set the data context to the List itself
lb_Parts.DataContext=myCollection;
Then you should be able to bind to it in the template
<DataTemplate x:Key="parts_template">
<StackPanel Orientation="Horizontal">
<TextBlock .../>
<ComboBox ItemSource={Binding}/>
</StackPanel>
</DataTemplate>

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