在TabControl中更改选项卡时,UI中未更新对ItemsControl的ItemsSource的更改

时间:2018-12-20 17:50:47

标签: c# wpf

我正在尝试创建一个TabControl中带有多个选项卡的wpf应用程序,其中一个选项卡是日志。第一个选项卡上的按钮在第二个选项卡的日志中添加一行。当按下按钮时,它还会显示一个消息框 包含日志ItemsSource的长度。 问题:

  • 按下按钮-出现消息框,其中显示日志中的一项
  • 切换到日志标签(显示一行)
  • 切换到按钮,然后按一下。该消息框在日志中显示2个项目。
  • 切换到日志标签,仅显示一项。

完整代码:

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;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

每当对源进行更改时,WPF技术都不会神奇地更新目标。它通过诸如DependencyObjectINotifyPropertyChangedINotifyCollectionChanged之类的通知机制来保持UI更新。

用于集合(List<>)的数据类型没有通知机制。因此,UI只会在创建时更新一次,而不会更新一次,这就是为什么您只有在第一次进入第二个选项卡时才会看到日志项的添加。

(不推荐),您可以执行此操作以在每次对其进行更改时手动重置ItemsSource。但是,它将始终在ItemsControl的可视树中重新创建所有UI元素。

private void SingleStep(object sender, RoutedEventArgs e)
{
    list.Add("STEP");
    LogList.ItemsSource = null;
    LogList.ItemsSource = list;
}

(推荐),您可以使用ObservableCollection-实现INotifyCollectionChanged-来实现对ItemsSource的绑定,如下所示:

ObservableCollection<string> _list = new ObservableCollection<string>();
public ObservableCollection<string> list { get { return _list; } }

请注意,ObservableCollection会在集合中 内自动将任何更改通知目标。