Reputation: 187
I am trying to create a wpf application with several tabs in a TabControl
, where one tab is a log. The button on the first tab adds a line to the log in the second tab. When the button is pressed, it also displays a message box
containing the length of the ItemsSource
of the log.
Issue:
Full Code:
MainWindow.xaml
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,10,10,10">
<TabItem Header="Microcode Process" Name="MicrocodeProcessTab">
<Button Content="Single Step" Margin="0,0,10,0" Click="SingleStep" Name="SingleStepButton"/>
</TabItem>
<TabItem Header="Log">
<ScrollViewer>
<ItemsControl Name="LogList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</TabItem>
</TabControl>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Windows;
namespace WpfApp2 {
public partial class MainWindow : Window {
List<string> list = new List<string>();
public MainWindow() {
InitializeComponent();
LogList.ItemsSource = list;
}
private void SingleStep(object sender, RoutedEventArgs e) {
list.Add($"STEP");
MessageBox.Show((LogList.ItemsSource as List<string>).Count.ToString());
e.Handled = true;
}
}
}
Upvotes: 1
Views: 622
Reputation: 17125
The WPF technology does not magically update target whenever a change is made to the source. It keeps UI updated through some notification mechanisms such as DependencyObject
, INotifyPropertyChanged
or INotifyCollectionChanged
.
The data type used for the collection (List<>
) does not have a notification mechanism. So the UI gets updated only once upon its creation and never again, that's why you see the log item added only the first time you go to the second tab.
(not recommended) You can do this to manually reset the ItemsSource every time a change is made to it. It will however always re-create all UI elements in the visual tree of the ItemsControl.
private void SingleStep(object sender, RoutedEventArgs e)
{
list.Add("STEP");
LogList.ItemsSource = null;
LogList.ItemsSource = list;
}
(recommended) You can implement binding for your ItemsSource by using an ObservableCollection
- which implements INotifyCollectionChanged
- as follows:
ObservableCollection<string> _list = new ObservableCollection<string>();
public ObservableCollection<string> list { get { return _list; } }
Note that an ObservableCollection
automatically notifies the target of any changes made within the collection.
Upvotes: 1