0
votes

i created a simple ListView in XAML which should bind to an ObservablaCollection:

<PivotItem x:Uid="pvItemMusic" Header="Music">
            <StackPanel>
                <TextBlock Name="tbSelectMusicHeader" Text="Select directories that should be included into your library" FontSize="18" Margin="20"></TextBlock>
                <Button Name="btnSelectSourcePath" Content="Add path" Margin="30,10,0,10" Click="btnSelectSourcePath_Click"></Button>
                <ListView Name="lvPathConfiguration" DataContext="{StaticResource configurationVM}" ItemsSource="{Binding MusicBasePathList, Mode=OneWay}">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <RelativePanel>
                                <TextBlock Name="tbPath" Text="{Binding Mode=OneWay}" RelativePanel.AlignTopWithPanel="True" VerticalAlignment="Center" Width="400" Margin="20"></TextBlock>
                                <Button Name="btnRemovePath" x:Uid="btnRemovePath" Content="Remove" RelativePanel.RightOf="tbPath" Margin="10" Height="48"></Button>
                            </RelativePanel>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackPanel>
        </PivotItem>

The namespace of my ViewModel is imported by

xmlns:applicationVM="using:Crankdesk.CrankHouseControl.ViewModel.Application"

and the Page Resource i added my ViewModel:

<Page.Resources>
        <applicationVM:ConfigurationViewModel x:Key="configurationVM"></applicationVM:ConfigurationViewModel>
    </Page.Resources>

btnSelectSourcePath should add a path to the list of source pathes that are stored in ViewModel, which will be done in CodeBehind:

private async void btnSelectSourcePath_Click(object sender, RoutedEventArgs e)
        {
            FolderPicker picker = new Windows.Storage.Pickers.FolderPicker();
            picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.MusicLibrary;
            picker.FileTypeFilter.Add("*");

            StorageFolder folder = await picker.PickSingleFolderAsync();

            if (folder != null)
            {
                // Save path to configuration
                App.ConfigurationViewModel.MusicBasePathList.Add(folder.Path);
            }
        }

In ViewModel the "INotifyPropertyChanged" Event is used and i use the "CollectionChanged" Event of my ObersableCollection to fire the PropertyChanged Event. When i add a path in debug mode, the RaisePropertyChanged Method will be executed, but the "handler" property is always NULL.

private void RaisePropertyChanged(string propertyName)
        {

            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

Here is my whole ViewModel:

namespace Crankdesk.CrankHouseControl.ViewModel.Application
{
    public class ConfigurationViewModel : INotifyPropertyChanged
    {    
        private ObservableCollection<string> _musicBasePathList;

        public ObservableCollection<string> MusicBasePathList
        {
            get
            {
                return _musicBasePathList; 
            }
            set
            {
                _musicBasePathList = value;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public ConfigurationViewModel()
        {
            _musicBasePathList = new ObservableCollection<string>();
            _musicBasePathList.CollectionChanged += _musicBasePathList_CollectionChanged;
        }

        private void _musicBasePathList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {   
            RaisePropertyChanged(nameof(MusicBasePathList));
        }


        private void RaisePropertyChanged(string propertyName)
        {

            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

What do i wrong here? I know i ask this question the 34th time here, but i didn't find a solution. In most cases they forgot to specify OneWay or TwoWay, but that's not the case here.

Thanks in advance....

Dave

1
And the code of the ViewModel is where? - Sir Rufo
Without a good minimal reproducible example that reliably reproduces the problem, it's not possible to know what the actual answer is. However, I guarantee it will wind up being some simple mistake in your data binding implementation. The two most likely candidates are: data context not set properly, or your model class has a PropertyChanged event but is not actually declared as implementing INotifyPropertyChanged. (And if you do improve your post and include a good minimal reproducible example, please go through and fix all the spelling errors and typos while you're at it...sloppy questions are less likely to get attention.) - Peter Duniho
You are right. i edited my post and added the ViewModel.... - David Koenig
There is no need to raise PropertyChanged on MusicBasePathList when the collection content has changed, because it is the same collection and it will do nothing on the view. But you should raise PropertyChanged inside the setter of MusicBasePathList - Sir Rufo
I don't think so. When i just Add something to the Collection, the setter will never be called. The setter will just be called, when i create a new Collection and write this to MusicBasePathList. - David Koenig

1 Answers

0
votes

You have at minimum two instances of ConfigurationViewModel in your application.

  1. App.ConfigurationViewModel
  2. defined in the page ressources as configurationVM

The view is bound to the 2. instance and in code behind you modify the 1. instance.