Binding all texts in TextBox from a html file - HtmlAgility - wpf

I have to make this app to show all texts from a html file, each text in his TextBox. so i did this ti'll now and i don't know how to continue:
.xaml.cs
public MainWindow()
{
InitializeComponent();
}
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
private void Button_Click_1(object sender, RoutedEventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.Filter = "HTM | *.htm";
if (open.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
doc.Load(open.OpenFile());
var listItems = doc.DocumentNode.SelectSingleNode("//ul").SelectNodes("li");
var src = new List<string>();
foreach (var li in listItems)
{
src.AddRange(li.Descendants("p").Select(x => x.InnerText));
}
myListBox.ItemsSource = src;
}
.xaml
<Grid>
<Button Content="Open" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
<ListBox Name="myListBox" HorizontalAlignment="Left" Height="249" Margin="10,48,0,0" VerticalAlignment="Top" Width="497">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Height="23" TextWrapping="Wrap" Width="400" Text="{Binding Description}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

Oh I think I see your problem... you're trying to data bind to a property named Description in your XAML. Would you like to show me where that property was declared, because I can't see one. Furthermore, your ListBox.ItemsSource is set to a List<string>, so there can't be any Description property to bind to. Instead, try this:
<TextBox Height="23" TextWrapping="Wrap" Width="400" Text="{Binding}" />

Related

Silverlight HyperlinkButton styles in custom control

I have a strange styling problem that I cannot figure out.
What I want to achieve is that HyperlinkButtons in datagrid cells are styled with an underline when the mouse hovers the link.
I have one column where I declare the HyperlinkButton element in XAML like this:
<HyperlinkButton Style="{StaticResource HyperlinkButtonStyle}" DataContext="{Binding}" FontSize="11" Content="{Binding DguNr}" Click="DgunrHyperlinkButtonClick" />
This works fine - the link is styled as I want.
In another column, I need to display n number of HyperlinkButtons based on some information in the bound element. Hence I have created a usercontrol that will render 0..n Hyperlinkbuttons. The control is declared in XAML like this:
<sdk:DataGridTemplateColumn IsReadOnly="True" CanUserSort="True">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<bc:BoreholePlantGridColumn Plants="{Binding Plants, Mode=OneWay}" />
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
The code behind for the control looks like this:
public partial class BoreholePlantGridColumn : UserControl, INotifyPropertyChanged
{
public BoreholePlantGridColumn()
{
InitializeComponent();
Loaded += new RoutedEventHandler(BoreholePlantGridColumn_Loaded);
}
void BoreholePlantGridColumn_Loaded(object sender, RoutedEventArgs e)
{
var borehole = (SelectableBoring)this.DataContext;
foreach(var p in borehole.Plants)
{
// <HyperlinkButton HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" DataContext="{Binding}" Foreground="Black" FontSize="11" Content="{Binding DguNr}" Click="DgunrHyperlinkButtonClick" />
var button = new HyperlinkButton();
button.Content = p.PlantId;
button.Style = (Style)App.Current.Resources["HyperlinkButtonStyle"];
button.VerticalContentAlignment = VerticalAlignment.Center;
var url = String.Format(Common.Constants.Url.GeusPlantLinkTemplate, p.PlantId);
button.NavigateUri = new Uri(url, UriKind.RelativeOrAbsolute);
button.TargetName = "_blank";
LayoutRoot.Children.Add(button);
}
}
public event PropertyChangedEventHandler PropertyChanged;
public static readonly DependencyProperty PlantsProperty = DependencyProperty.Register("Value", typeof(Anlaeg), typeof(BoreholePlantGridColumn), new PropertyMetadata(new PropertyChangedCallback(ValueChanged)));
public IList<Anlaeg> Plants
{
get { return (IList<Anlaeg>)this.GetValue(PlantsProperty); }
set { this.SetValue(PlantsProperty, value); }
}
private static void ValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var myUC = (BoreholePlantGridColumn)obj;
var newValue = (IList<Anlaeg>)e.NewValue;
}
}
This works almost as expected; the linkbuttons(s) are rendered with the correct color - but there is not displayed an underline text when the mouse hovers the link.
I do not understand why the underline is displayed in the hyperlinkbutton that is declared directly in XAML but not in the hyperlink that is rendered in code-behind. Can someone please help me on this?
I have used the hyperlinkbutton styling from this thread:1
I just use the Following Code
<ListBox Grid.Column="1" ItemsSource="{Binding EncyclopediaList}" HorizontalContentAlignment ="Stretch" Margin="5,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<HyperlinkButton Content="{Binding Name}" Foreground="Black" Command="{Binding ViewArticlePageCommand, Source={StaticResource EncyclopediaViewModel}}" CommandParameter="{Binding ServerEncyclopediaID}" FontFamily="Arial" FontSize="18" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
No need to Style the HyperlinkButton its Works perfectly in My Case Add the Underline and Make it bold when Mouse move over it.

How to change data in a Silverlight DataContext Object

I have a datacontext object that displays a list of uploaded files, and number of copies. So far, the user can click an edit icon that is in each row, and retrieve the data in that row, but I do not know how to change any data.
Here is the button event for the 'change details' dialog on the main page:
private void Image_MouseLeftButtonUp_1(object sender, MouseButtonEventArgs e)
{
Image b = sender as Image;
FileReceivedItem fi = b.DataContext as FileReceivedItem;
string fileCopies = fi.fileCopies;
string fileName = fi.FileName;
DetailsWindow detailsDlg = new DetailsWindow(fileCopies, fileName);
detailsDlg.Show();
detailsDlg.Closed += new EventHandler(detailsWnd_Closed);
}
public DetailsWindow detailsDlg;
void detailsWnd_Closed(object sender, EventArgs e)
{
MessageBox.Show("I want to change fileCopies here");
}
The relevant portions of the XAML:
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Hidden" ItemsSource="{StaticResource FileReceivedItem}" Name="filesReceivedList" HorizontalAlignment="Left" Grid.Row="1" Grid.Column="1" Background="White" Margin="12,23,0,0"
VerticalAlignment="Top" Width="411" Height="175" Loaded="filesReceivedList_Loaded">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Width="404" Height="19" Orientation="Horizontal" >
<TextBlock x:Name="ListFileName" Text="{Binding FileName}" Width="283" VerticalAlignment="Center">
<ToolTipService.ToolTip>
<ToolTip Content="{Binding FileName}"></ToolTip>
</ToolTipService.ToolTip>
</TextBlock>
<TextBlock Text="{Binding fileCopies}" Width="50" VerticalAlignment="Center"/>
<TextBlock Text="{Binding FileID}" Width="0" Visibility="Collapsed" VerticalAlignment="Center"/>
<Image Source="images/Edit.png" MouseLeftButtonUp="Image_MouseLeftButtonUp_1" Width="20" Margin="0 0 0 0">
<ToolTipService.ToolTip>
<ToolTip Content="Edit"></ToolTip>
</ToolTipService.ToolTip>
</Image>
<TextBlock Text="" Width="10" />
<Image Source="images/Delete.png" MouseLeftButtonUp="Image_MouseLeftButtonUp" >
<ToolTipService.ToolTip>
<ToolTip Content="Delete"></ToolTip>
</ToolTipService.ToolTip>
</Image>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Let me know if any important pieces of code are missing. I'm not sure how the data source works exactly.
I eventually got it to work. Pretty straightforward. I just haven't used SL in ahwile. This is what I did, although there might be a better way that someone might provide as a better answer:
void detailsWnd_Closed(object sender, EventArgs e)
{
changeFileCopies(detailsDlg.FileName, detailsDlg.nCopies.Text);
}
public void changeFileCopies(string filename, string newCopies)
{
var row = (FileReceivedItem)filesReceivedDataSource.Where(x => x.FileName == filename).FirstOrDefault();
row.fileCopies = newCopies;
filesReceivedList.ItemsSource = null;
this.filesReceivedList.ItemsSource = filesReceivedDataSource;
}

how to get textbox value from View to ViewModel in Silverlight MVVM?

Currently now i'm using silverlight5 with MVVM. in SL5 i need to do the following.
I have 3 textbox and 1 button control and i datagrid in the xaml(Design page).
here is the Design View(Xaml):
<UserControl.DataContext>
<VC:EmployeeListViewModel />
</UserControl.DataContext>
<Grid x:Name="LayoutRoot">
<my:DataGrid x:Name="McDataGrid" ItemsSource="{Binding Employees,UpdateSourceTrigger=PropertyChanged}" Margin="130,151,0,0" Height="137" VerticalAlignment="Top" RowBackground="#AA5D9324" AutoGenerateColumns="True" HorizontalAlignment="Left" Width="193">
</my:DataGrid>
<Button Content="Show Message" Width="100" Height="25" Margin="256,75,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<si:CallDataMethod Method="AddEmployeeCommand"/>
<si:ShowMessageBox Caption="Thank you"
Message="Thanks for trying the Example"
MessageBoxButton="OK"/>
<si:SetProperty TargetName="LayoutRoot"
PropertyName="Background" Value="PaleGoldenrod"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<TextBlock FontWeight="Bold" Height="26" HorizontalAlignment="Left" Margin="47,12,0,0" Name="textBlock1" Text="First Name:" VerticalAlignment="Top" Width="77" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="130,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Employee.Fname}" />
<TextBlock FontWeight="Bold" Height="25" HorizontalAlignment="Left" Margin="35,44,0,0" Name="textBlock2" Text="Second Name:" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="130,44,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" />
<TextBlock FontWeight="Bold" Height="23" HorizontalAlignment="Left" Margin="45,75,0,0" Name="textBlock3" Text="Department:" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="130,75,0,0" Name="textBox3" VerticalAlignment="Top" Width="120" />
<!-- Add reference to Microsoft.Expression.Interactions.dll, System.Windows.Interactivity.dll -->
<!-- Use mvvmxmlns snippet to add i and ei namespace prefixes -->
</ComboBox>
<TextBlock Height="23" HorizontalAlignment="Left" Margin="64,122,0,0" Name="textBlock4" Text="Choose:" VerticalAlignment="Top" FontWeight="Bold" />
</Grid>
</UserControl>
in the same project i create one folder named 'ViewModel':
in the same folder i add one class file named: EmployeeListViewModel.cs
my question is this. how to pass the textbox value to the viewmodel[EmployeeListViewModel] and insert the it to the Datagrid.
EmployeeListViewModel.cs:
public class EmployeeListViewModel:INotifyPropertyChanged
{
public ObservableCollection<Employee> Employees { get; private set; }
public EmployeeListViewModel()
{
Employees = Silverlight_MVVM.DataHelper.EmployeeDataHelper.EmployeeData ();
}
private Employee _SelectedEmployee;
public Employee SelectedEmployee
{
get
{
return _SelectedEmployee;
}
set
{
_SelectedEmployee = value;
RaisePropertyChanged("SelectedEmployee");
}
}
private Employee _Names;
public Employee Names
{
get
{
return _Names;
}
set
{
_Names = value;
RaisePropertyChanged("Names");
}
}
public void HandleShowMessage()
{
// MessageBox.Show("Hello " + Names + ",Welcome to EventTrigger for MVVM.");
}
public RelayCommand _AddEmployeeCommand;
/// <summary>
/// Returns a command that show the customer.
/// </summary>
public ICommand AddEmployeeCommand
{
get
{
if (_AddEmployeeCommand == null)
{
_AddEmployeeCommand = new RelayCommand(
param => this.AddEmployee(),
param => this.CanAddEmployee
);
}
return _AddEmployeeCommand;
}
}
public bool CanAddEmployee
{
get
{
return true;
}
}
public void AddEmployee()
{
//Employee newEmployee = new Employee("New1);
Employee newEmployee = new Employee() **{};**
--> **Here i have to pass the value.. How is it possible..?**
Employees.Add(newEmployee);
SelectedEmployee = newEmployee;
}
#region INotifyPropertyChanged
// [field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
Not 100% sure how you are going about this?
Usually I would have the grid bound to the selected employee as you have, then have the values of the text boxes bound to the properties on the selectedemployee. As you change row, these would then update to reflect the values of the currently selected row in the grid.
So then you add a new blank employee and it would have blank values until they were entered in the text box. Of course, you'd need to build in some validation to ensure you don't get loads of blabnk rows added.
If I'm correct in my understanding of how you are wanting to do it, then as it stands the values in the text boxes are not related to the selected row, but are used just to add a new employee with those values? to achieve this I would suggest having the Textbox bind to a string value on the Viewmodel. Currently you have them bound to something that doesn't appear to actually exist. Instead, I'd bind them to their own properties on the view model thus:
private string _employeeFirstName;
public string EmployeeFirstName
{
get
{
return _employeeFirstName;
}
set
{
_employeeFirstName= value;
RaisePropertyChanged("EmployeeFirstName");
}
}
and then in the xaml bind to that property - with Mode=TwoWay so that the viewmodel also recieves any updates
<TextBox Height="23" HorizontalAlignment="Left" Margin="130,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=EmployeeFirstName, Mode=TwoWay}" />
then when creating your new employee:
public void AddEmployee()
{
Employee newEmployee = new Employee() {FName = this.EmployeeFirstName};
Employees.Add(newEmployee);
SelectedEmployee = newEmployee;
}
You have to use TwoWay binding mode. For example, Text="{Binding Path=Employee.Fname,Mode=TwoWay}". You can read more about Binding.Mode on MSDN.
i create three property named Fname,Sname,Dept respectly in View Model..
private string _fname;
public string Fname
{
get
{
return _fname;
}
set
{
_fname = value;
RaisePropertyChanged("Fname");
}
}
And the function is as follows..
public void AddEmployee()
{
Employee newEmployee = new Employee() {Fname=this.Fname;Sname=this.Sname;Dept=this.Dept};
Employees.Add(newEmployee);
SelectedEmployee = newEmployee;
}
It Works Well..
Design Code is :
<TextBlock FontWeight="Bold" Height="26" HorizontalAlignment="Left" Margin="47,12,0,0" Name="textBlock1" Text="First Name:" VerticalAlignment="Top" Width="77" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="130,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="{Binding Path=Fname,Mode=TwoWay}" />
<TextBlock FontWeight="Bold" Height="25" HorizontalAlignment="Left" Margin="35,44,0,0" Name="textBlock2" Text="Second Name:" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="130,44,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" Text="{Binding Path=Sname,Mode=TwoWay}"/>
<TextBlock FontWeight="Bold" Height="23" HorizontalAlignment="Left" Margin="45,75,0,0" Name="textBlock3" Text="Department:" VerticalAlignment="Top" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="130,75,0,0" Name="textBox3" VerticalAlignment="Top" Width="120" Text="{Binding Path=Dept,Mode=TwoWay}"/>
<Button Content="Show Message" Width="100" Height="25" Margin="256,75,0,0" VerticalAlignment="Top" HorizontalAlignment="Left">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<si:CallDataMethod Method="AddEmployee"/>
<si:ShowMessageBox Caption="Thank you"
Message="Thanks for trying the Example"
MessageBoxButton="OK"/>
<si:SetProperty TargetName="LayoutRoot"
PropertyName="Background" Value="PaleGoldenrod"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Hope it will useful to us..

XML Parsing Error in Window Phone

I'm creating a tweeter example in window phone and got NullReferenceException
I think it might be that the syntax is incorrect on the right side of the expression but couldn't tell what and why..
Anyone has an idea why this resulted in error?
.xaml.cs:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
string url = "http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=noradio";
WebClient twitter = new WebClient();
twitter.DownloadStringCompleted += new DownloadStringCompletedEventHandler(twitter_DownloadStringCompleted);
twitter.DownloadStringAsync(new Uri(url));
}
void twitter_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error != null)
return;
XElement xmlTweets = XElement.Parse(e.Result);
listBox1.ItemsSource = from tweet in xmlTweets.Descendants("Status")
select new TweeterItem
{
ImageSource = tweet.Element("user").Element("profile_image_url").Value,
Message = tweet.Element("text").Value,
UserName = tweet.Element("user").Element("screen_name").Value,
};
}
.xaml:
<ListBox Height="521" HorizontalAlignment="Left" Margin="0,131,0,0" Name="listBox1" VerticalAlignment="Top" Width="476">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="132">
<Image Source="{Binding ImageSource}" Height="73" Width="73" VerticalAlignment="Top" Margin="0,10,8,0"/>
<StackPanel Width="370">
<TextBlock Text="{Binding UserName}" Foreground="#FFC8AB14" FontSize="28" />
<TextBlock Text="{Binding Message}" TextWrapping="Wrap" FontSize="24" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I usually do something like this, then I can check the values for null afterwards:
XmlReader xmlReader = XmlReader.Create(e.Result as Stream);
while (xmlReader.Read())
{
if (xmlReader.NodeType == XmlNodeType.Element)
{
switch (xmlReader.Name)
{
case "profile_image_url":
ImageSource = xmlReader.ReadInnerXml();
break;
case "text":
Message = xmlReader.ReadInnerXml();
break;
case "screen_name":
UserName = xmlReader.ReadInnerXml();
break;
}
}
}

How to access Button programatically if the button is inside using C#

I have few questions as I am usign XAML for the first time.
How do I use the button (BrowseButton) to browse a folder in Harddrive ?
In this case as the button is inside
Can I use the way I have shown below?
Actually first dockpanel will hold the image and some label and the other dockpanel will have tabcontrol in it.
If I have a tabcontrol, How can I add a listview which can increase the tabs during runtime.. and the listview should be available in the runtime also.
How to add a close("X") mark on the top of the tab to close the button
probably I asked a lot of questions, sorry :(
Please help
<Grid>
<DockPanel>
<StackPanel>
<Image Name="imgClientPhoto" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto" Height="auto" Grid.Column="0" Grid.Row="0" Margin="0"
Source="D:ehtmp_top_left.gif" MinWidth="450" MinHeight="100" Grid.IsSharedSizeScope="True">
</Image>
<Button x:Name="BrowseButton" Margin="0,13.638,30,14.362" Content="Browse" Click="BrowseButton_Click" HorizontalAlignment="Right" Width="111" />
<TextBox x:Name="txtBxBrowseTB" Margin="46,10,146,10" Text="TextBox" TextWrapping="Wrap" TextChanged="BrowseTB_TextChanged"></TextBox>
<Label HorizontalAlignment="Left" Margin="-14,22,0,10" Name="label1" Width="69.75" FontSize="13" VerticalContentAlignment="Top" HorizontalContentAlignment="Center">Path:</Label>
</Grid>
</GroupBox>
</Grid>
</StackPanel>
</DockPanel>
<DockPanel>
<StackPanel Margin="0,158,0,0" HorizontalAlignment="Left" Width="330" Height="557.5" VerticalAlignment="Top">
<TextBox Height="50" Name="textBox1" Width="240" Margin="0,35,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Right" />
<ListBox Height="470" Name="listBox1" Width="332" Background="LightGray" Margin="0,0,0,0" BorderBrush="IndianRed" BorderThickness="3" />
</StackPanel>
<TabControl Height="234" Name="tabControl1" Width="1035" Margin="0,0,0,0">
<TabItem Header="tabItem1" Name="tabItem1">
<Grid Height="144" />
</TabItem>
</TabControl>
</DockPanel>
</Grid>
1) The browse code should be something like this:
private void BrowseButton_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.FolderBrowserDialog browse = new System.Windows.Forms.FolderBrowserDialog();
browse.RootFolder= Environment.SpecialFolder.MyDocuments;
browse.SelectedPath = "C:\\InitalFolder\\SomeFolder";
if (browse.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtBxBrowseTB.Text = browse.SelectedPath;
}
}
2) I have tried to simplify the xaml. Does this look like something you could go with?:
<Grid>
<Image Name="imgClientPhoto" Margin="0" Height="262" VerticalAlignment="Top" HorizontalAlignment="Left" ></Image>
<StackPanel VerticalAlignment="Stretch" >
<StackPanel VerticalAlignment="Top" Orientation="Horizontal" Height="30">
<Button Name="BrowseButton" Content="Browse" Click="BrowseButton_Click" HorizontalAlignment="Right" Width="111" />
<Label Name="label1" Width="69.75" FontSize="13" VerticalContentAlignment="Center" HorizontalContentAlignment="Right">Path:</Label>
<TextBox Name="txtBxBrowseTB" Width="200" Text="TextBox" VerticalContentAlignment="Center" TextWrapping="Wrap" TextChanged="BrowseTB_TextChanged"></TextBox>
</StackPanel>
<StackPanel>
<StackPanel Orientation="Vertical">
<TextBox Height="50" Name="textBox1" />
<ListBox Height="470" Name="listBox1" Background="LightGray" Margin="0,0,0,0" BorderBrush="IndianRed" BorderThickness="3" MouseLeftButtonUp="listBox1_MouseLeftButtonUp">
<ListBoxItem>User1</ListBoxItem>
<ListBoxItem>User2</ListBoxItem>
<ListBoxItem>User3</ListBoxItem>
<ListBoxItem>User4</ListBoxItem>
</ListBox>
</StackPanel>
<TabControl Name="tabControl1" />
</StackPanel>
</StackPanel>
</Grid>
You can also have a close button in the tab item Header. As many of the content properties in xaml controls, the content can actually be controls, and not necessary just a text.
<TabControl Name="tabControl1" >
<TabItem Name="tabItem1" >
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Label>TabHeader1</Label>
<Button Height="20" Width="20" FontWeight="Bold" Click="CloseTabButton_Click">X</Button>
</StackPanel>
</TabItem.Header>
<Grid Height="144">
<ListView />
</Grid>
</TabItem>
</TabControl>
3) Here is how you would add the tabs in C# dynamically:
private void listBox1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//Get selected item
ListBoxItem item = (ListBoxItem)listBox1.SelectedItem;
string itemText = item.Content.ToString();
//Check if item is already added
foreach (TabItem tItem in tabControl1.Items)
{
if ((string)tItem.Tag == itemText)
{
//Item already added, just activate the tab
tabControl1.SelectedItem = tItem;
return;
}
}
//Build new tab item
TabItem tabItem = new TabItem();
tabItem.Tag = itemText;
//First build the Header content
Label label = new Label();
Button button = new Button();
label.Content = itemText;
button.Content = "X";
button.Height = 20;
button.Width = 20;
button.FontWeight = FontWeights.Bold;
button.Click += CloseTabButton_Click; //Attach the event click method
button.Tag = tabItem; //Reference to the tab item to close in CloseTabButton_Click
StackPanel panel = new StackPanel();
panel.Orientation = Orientation.Horizontal;
panel.Children.Add(label);
panel.Children.Add(button);
tabItem.Header = panel;
//Then build the actual tab content
//If you need only the ListView in here, you don't need a grid
ListView listView = new ListView();
//TODO: Populate the listView with what you need
tabItem.Content = listView;
//Add the finished tabItem to your TabControl
tabControl1.Items.Add(tabItem);
tabControl1.SelectedItem = tabItem; //Activate the tab
}
private void CloseTabButton_Click(object sender, RoutedEventArgs e)
{
//The tab item was set to button.Tag when it was added
Button button = (Button)sender;
TabItem tabItem = (TabItem)button.Tag;
if (tabItem != null)
{
button.Click -= CloseTabButton_Click; //Detach event handler to prevent memory leak
tabControl1.Items.Remove(tabItem);
}
}

Resources