0

In my project, I have a Combobox and a Treeview. A dictionary Dictionary<string, ObservableCollection<ViewItem>> is the item source of the Combobox, and the DisplayMemberPath is the Key. It read existing Json files in a certain directory. The item source of the Treeview is bound to the Combobox and the Path is SelectedItem.Value. Then a button has a command to update the dictionary, basically to add a new entry. I have implemented the INotifyPropertyChanged interface but the Combobox is not updated after the button is clicked.

The following are the codes:

XAML:

<GroupBox Header="Template" Grid.Column="1" Grid.Row="0" Grid.RowSpan="6" Margin="10,10,10,10">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="10*"/>
            </Grid.RowDefinitions>
            <ComboBox x:Name="templateCombobox" Grid.Row="0" Margin="5,10,5,10" ItemsSource="{Binding LoadedTemplateViews,Mode=TwoWay,NotifyOnSourceUpdated=True,UpdateSourceTrigger=PropertyChanged}"  DisplayMemberPath="Key" SelectedValue="{Binding SelectedItem}" SelectedValuePath="Key"/>
            <TreeView Name="templateTreeview"
           ItemsSource="{Binding ElementName=templateCombobox, Path=SelectedItem.Value}"
           FontSize="14"
           Grid.Row="2"          
           AllowDrop="True" Margin="5,5,5,10">
                <i:Interaction.Behaviors>
                    <local:DragDropBehavior />
                </i:Interaction.Behaviors>
                <TreeView.ItemContainerStyle>
                    <Style TargetType="{x:Type TreeViewItem}">
                        <Setter Property="IsExpanded" Value="True" />
                    </Style>
                </TreeView.ItemContainerStyle>
                <TreeView.Resources>
                    <HierarchicalDataTemplate DataType="{x:Type model:ViewItem}" ItemsSource="{Binding Path=ViewItems}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Path=ItemName}" Margin="0,0,10,0" />
                            <Button Name="DeleteTreeViewItem" Background="Transparent" BorderBrush="Transparent" Click="DeleteTreeViewItem_Click" Visibility="{Binding Path=IsVisible,Converter={StaticResource IntConverter}}">
                                <Image Source="delete_cross.png" Height="15" />
                            </Button>
                        </StackPanel>
                    </HierarchicalDataTemplate>
                </TreeView.Resources>
            </TreeView>
        </Grid>
    </GroupBox>
<Button Content="CREATE" Grid.Column="1" Grid.Row="1" Command="{Binding CreateTemplateJsonCommand}" />

ViewModeBase class

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Simplified ViewModel, it inherits ViewModelBase:

    private Dictionary<string, ObservableCollection<ViewItem>> _loadedTemplateViews;

    public Dictionary<string, ObservableCollection<ViewItem>> LoadedTemplateViews
    {
        get { return _loadedTemplateViews; }
        set { _loadedTemplateViews = value; OnPropertyChanged(nameof(LoadedTemplateViews)); }
    }
    public TemplateViewModel(TemplateDetailsStore templateDetailsStore)
    {
        
        LoadedTemplateViews = templateViewUIDataService.TemplatesInfo;
        CreateTemplateJsonCommand = new CreateTemplateJsonCommand(templateDetailsStore, this);
    }

The templateViewUIDataService.TemplatesInfo reads local JSON files and returns a dictionary. The key is the filename and the value is the desired data.

Simplified CreateTemplateJsonCommand:

internal class CreateTemplateJsonCommand : CommandBase
{
    private readonly TemplateDetailsStore _store;
    private readonly TemplateView1Model _viewModel;

    public CreateTemplateJsonCommand(TemplateDetailsStore store, TemplateView1Model viewModel)
    {
        _store = store;
        _viewModel = viewModel;
    }

    public override void Execute(object parameter)
    {
            _viewModel.LoadedTemplateViews.Add(_viewModel.templateFileName, new ObservableCollection<ViewItem> { _store.currentTemplateDetails.TreeviewDetail } );
        }
    }
}

Now I click the Create button, and the new entry is added to the item source dictionary, I can see that in debug mode. But the Combobox is not refreshed. I cannot see the created value from the dropdown of the Combobox.

Can someone give me a hint of where I did wrong? Thank you.

Aqib Chattha
  • 197
  • 11
BabyHai
  • 89
  • 1
  • 9
  • 2
    I believe you'll have to replace Dictionary> with something else since Dictionary doesn't implement INotifyCollectionChanged or INotifyPropertyChanged. This answer may be helpful https://stackoverflow.com/questions/3818365/wpf-how-can-i-implement-an-observablecollectionk-t-with-a-key-like-a-dictio – bigcrazyal Aug 21 '23 at 20:22
  • @bigcrazyal Thank you. That is the point I missed. I have solved it by using two `ObservableCollection` lists. – BabyHai Aug 22 '23 at 09:22

0 Answers0