简体   繁体   中英

Updating TabControl ItemSource ViewModels when specific state changes

I have a TabControl bound to an ObservableCollection property of view models, TabViewModelsCollection .

When another property gets set from within the view models, DeviceState , I'd like to raise a property changed event and tell my TabControl s ItemSource to refresh.

The problem is my ItemSource is an ObservableCollection of ViewModels and when I call RaisePropertyChanged("TabViewModelsCollection"); nothing gets updated.

Furthermore my tab views contain multiple user controls and bindings.

The scenario that is supposed to play out is: A device is located on the network, data is collected, and the tabs of device information should then be updated.

Currently my TabControl only updates when I select a different device then select the device whos information I want to see. Think left panel list of devices, right panel with tabs of device info.

Let me know what part of the code you guys might want to see, my codebase is quite large so it would be hard to post it.

Here is where the TabControl is defined in my view:

 <!-- Devist List Controls -->
        <Grid DockPanel.Dock="Left" Margin="5,5">
            <local:DeviceListView DataContext="{Binding DeviceListViewModel}" Grid.Row="0"/>
        </Grid>
        <GroupBox Header="Device Information" DockPanel.Dock="Right" Margin="0,0,5,5">
            <TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding DeviceListViewModel.SelectedDevice.TabViewModelsCollection}" SelectedItem="{Binding DeviceListViewModel.SelectedDevice.SelectedTabItemVm}"   >
                <TabControl.Resources>
                    <DataTemplate DataType="{x:Type vms:HomeViewModel}">
                        <local:HomeTab/>
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type vms:ConfigurationViewModel}">
                        <Grid>
                            <local:ConfigurationFileView  Visibility="{Binding Configuration, TargetNullValue=Collapsed, FallbackValue=Visible}"/>
                            <local:ErrorTab  Visibility="{Binding Path= Configuration, TargetNullValue=Visible, FallbackValue=Hidden}"/>
                        </Grid>
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type vms:ExpansionModulesViewModelFactory}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="35"/>
                            </Grid.RowDefinitions>
                            <StackPanel Grid.Row="0">
                                <DockPanel >
                                    <local:ExpansionModulesList Title="Discovered/Enumerated" 
                                                        DataContext="{Binding DiscoveredModules}" 
                                                       />
                                    <GridSplitter Width="5"/>
                                    <local:ExpansionModulesList Title="User Action Required" 
                                                        DataContext="{Binding FaultyModules}" 
                                                        />
                                </DockPanel>
                            </StackPanel>
                            <DockPanel Grid.Row="1">
                                    <StackPanel Orientation="Horizontal" FlowDirection="RightToLeft" Margin="5" IsEnabled="{Binding IsCommandEnabled}">
                                        <Button Content="Cancel" HorizontalAlignment="Right"             
                                             Command="{Binding CancelExpansionCommand }"
                                             ToolTip="Revert all local modifications by refreshing data from the controller." />                                                                                                                                  
                                        <Separator Width="10"/>

                                        <Button Content="Apply"  HorizontalAlignment="Center"                         
                                             Command="{Binding ApplyExpansionCommand }"
                                             ToolTip="Apply all changes to the controller." />
                                        <Separator/>
                                    </StackPanel>
                                </DockPanel>

                        </Grid>
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type vms:LogViewModel}">
                        <local:LogView  />
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type vms:SignalStrengthViewModel}">
                        <local:SignalStrengthView  />
                    </DataTemplate>
                </TabControl.Resources>

                <TabControl.ItemContainerStyle>

                    <Style TargetType="{x:Type TabItem}">
                        <Setter Property="Header" Value="{Binding Name}" />
                        <Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
                        <Setter Property="Header" Value="{Binding Name}" />
                    </Style>
                </TabControl.ItemContainerStyle>

EDIT: I want to be able to call raised property changed on this and have it refresh all of my tab views..

<TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding DeviceListViewModel.SelectedDevice.TabViewModelsCollection}" SelectedItem="{Binding DeviceListViewModel.SelectedDevice.SelectedTabItemVm}"   >

RaisePropertyChanged("TabViewModelsCollection");

Hi please try the next solution:

VM code redaction

    private State _deviceState;
    private ObservableCollection<object> _tabViewModelsCollection;
    public State DeviceState
    {
        get { return _deviceState; }
        set
        {
            _deviceState = value;
            RaisePropertyChanged("DeviceState");
            UpdateTabViewModelsCollection();
        }
    }

    public ObservableCollection<object> TabViewModelsCollection
    {
        get
        {
            return _tabViewModelsCollection ??
                   (_tabViewModelsCollection = new ObservableCollection<object>(GetDeviceData()));
        }
    }

    private void UpdateTabViewModelsCollection()
    {
        _tabViewModelsCollection = null;
        RaisePropertyChanged("TabViewModelsCollection");
    }

    private List<object> GetDeviceData()
    {
        //implement here the data collection process
        throw new NotImplementedException();
    }

Xaml redaction (define the UpdateSourceTrigger)

    ItemsSource="{Binding DeviceListViewModel.SelectedDevice.TabViewModelsCollection, UpdateSourceTrigger=PropertyChanged}"

Let me know if it was helpful.

Regards.

I'm experiencing a similar problem.

Did the OP ever resolve this?

What did you do to make the current tab refresh when you changed the ViewModel, and thus, by association, the View bound to it? For me the user has to click on the current tab to force the bound View's controls to appear on it.

Thanks

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