简体   繁体   中英

Adding elements to ObservableCollection doesn't update UI

I want a TabControl with dynamic TabItems . I have an ObservableCollection property in my code-behind file and when I add elements to this property I expect the GUI to add a new TabItem element.

MainWindow.xaml

<TabControl ItemsSource="{Binding ElementName=Window, Path=PositionTabs, Mode=OneWay}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Header, Mode=OneTime}"></TextBlock>
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Content, Mode=OneTime}"></TextBlock>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public ObservableCollection<PositionTab> PositionTabs { get; set; }

    public MainWindow()
    {
        InitializeComponent();

        PositionTabs = new ObservableCollection<PositionTab>();

        for (int i = 0; i <= 4; i++)
        {
            PositionTabs.Add(new PositionTab(i));
        }
    }
}

PositionTab.cs

public class PositionTab
{
    public int PosIndex { get; }
    public string Header => $"Position {PosIndex + 1}";  
    public string Content => "Content";

    public PositionTab(int posIndex)
    {
        PosIndex = posIndex;
    }
}

When I start my application I only have a empty TabControl .

You could just move the set up of your data:

    public MainWindow()
    {
        PositionTabs = new ObservableCollection<PositionTab>();

        for (int i = 0; i <= 4; i++)
        {
            PositionTabs.Add(new PositionTab(i));
        }

        InitializeComponent();


    }

The problem you're seeing is that the observablecollection is null initially. This is something most mvvm developers will never see happen so it looks weird to us. I'd normally have a viewmodel, that would implement inotifypropertychanged and when I set up such a collection it would raise property changed on the collection and it'd all just work. To do this all in code behind is not usual practice... but... to show that working:

public partial class MainWindow : Window,  INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public ObservableCollection<PositionTab> PositionTabs { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        PositionTabs = new ObservableCollection<PositionTab>();
        RaisePropertyChanged("PositionTabs");
        for (int i = 0; i <= 4; i++)
        {
            PositionTabs.Add(new PositionTab(i));
        }

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM