ObservableCollection.CollectionChanged does not select the correct DataTemplate on ToolBar

240 views Asked by At

I have a ToolBar with 3 DataTemplates for my Items:

  <ToolBar ItemsSource="{Binding ContextActions}" Background="Transparent" ToolBarTray.IsLocked="True">
        <ToolBar.Resources>
            <DataTemplate DataType="{x:Type viewModels:SimpleContextActionViewModel}">
                <Button Command="{Binding ActionCommand}" Style="{StaticResource ToolBarButtonStyle}" ToolTip="{userInterface:Translation Binding={Binding ToolTip}}">
                    <ContentControl Template="{Binding Icon,Converter={StaticResource NameToResourceConverter}}" Margin="5" />
                </Button>
            </DataTemplate>
            <DataTemplate DataType="{x:Type viewModels:SeparatorViewModel}">
                <Rectangle Fill="{StaticResource SeparatorBrush}" Width="1" VerticalAlignment="Stretch" Margin="2,7" />
            </DataTemplate>
            <DataTemplate DataType="{x:Type viewModels:PopupContextActionViewModel}">
                <Grid>
                    <ToggleButton IsChecked="{Binding ElementName=ContextActionPopup, Mode=TwoWay,Path=IsOpen}" Style="{StaticResource ToolBarButtonStyle}"
                                  ToolTip="{userInterface:Translation Binding={Binding ToolTip}}">
                        <ContentControl Template="{Binding Icon, Converter={StaticResource NameToResourceConverter}}" Margin="5" />
                    </ToggleButton>
                    <Popup Name="ContextActionPopup" Height="150" Width="150" StaysOpen="False">
                        <Border BorderBrush="{StaticResource PopupBorderBrush}" BorderThickness="1" Background="White">
                            <ContentControl userInterface:RegionHelper.RegionName="{Binding RegionId}" />
                        </Border>
                    </Popup>
                </Grid>
            </DataTemplate>
        </ToolBar.Resources>
    </ToolBar>

The ItemsSource is a ObservableCollection<object>

The first three items are already available in the constructor of my ViewModel, those three use the DataTemplates as expected.

If I add another "SimpleContextActionViewModel" to the ObservableCollection, the ToolBar only adds a ContentPresenter which calls ToString. If I add the following line to reasign the ObservableCollection to a new one, everything works fine:

this.ContextActions = new ObservableCollection<object>(this.ContextActions);

this triggers the NotifyPropertyChanged Implementation of my ViewModel and all Items are recreated and look fine.

Why does a CollectionChanged of my ObservableCollection not select a valid DataTemplate while PropertyChanged does?.

This is how it looks This is how it looks

2

There are 2 answers

2
Krishna On BEST ANSWER

I have seen this happen before with the toolbar when used with the collection getting changed anywhere other than the constructor.

Instead of adding your data templates in toolbar resources, add them to the app.xaml then you will see that your code will work as it should. Try this and let me know if it is still not working

1
Bobby On

I'm not certain whether this applies in your case, but your problem seems remarkably similar to: Wiring up CollectionChanged and PropertyChanged (Or : Why do some WPF Bindings not refresh?)

From the accepted answer on that link:

If you don't provide WPF with a template for a data item (such as the Person objects in your list), it'll default to using the ToString() method to display. That's a member, not a property, and so you get no event notification when the value changes.

If you add DisplayMemberPath="Name" to your listbox, it'll generate a template that binds properly to the Name of your person - which will then update automatically as you'd expect.

Could you apply a DisplayMemberPath to the toolbox so that it does not use ToString() by default to render, but rather triggers the NotifyPropertyChanged?