【发布时间】:2018-02-03 03:08:00
【问题描述】:
我在 XAML 中创建了一个简单的 ListView,它应该绑定到 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>
我的 ViewModel 的命名空间是由
导入的xmlns:applicationVM="using:Crankdesk.CrankHouseControl.ViewModel.Application"
我添加了我的 ViewModel 的页面资源:
<Page.Resources>
<applicationVM:ConfigurationViewModel x:Key="configurationVM"></applicationVM:ConfigurationViewModel>
</Page.Resources>
btnSelectSourcePath 应该将路径添加到存储在 ViewModel 中的源路径列表中,这将在 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);
}
}
在 ViewModel 中使用了“INotifyPropertyChanged”事件,我使用 ObersableCollection 的“CollectionChanged”事件来触发 PropertyChanged 事件。当我在调试模式下添加路径时,将执行 RaisePropertyChanged 方法,但“处理程序”属性始终为 NULL。
private void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
这是我的整个 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));
}
}
}
}
我在这里做错了什么?我知道我在这里第 34 次问这个问题,但我没有找到解决方案。在大多数情况下,他们忘记指定 OneWay 或 TwoWay,但这里不是这种情况。
提前谢谢....
戴夫
【问题讨论】:
-
而ViewModel的代码在哪里?
-
如果没有可靠地重现问题的良好minimal reproducible example,就不可能知道实际答案是什么。但是,我保证它最终会成为您的数据绑定实现中的一些简单错误。最有可能的两个候选者是:数据上下文设置不正确,或者您的模型类具有
PropertyChanged事件但实际上并未声明为实现INotifyPropertyChanged。 (如果你确实改进了你的帖子并添加了一个好的minimal reproducible example,请在你写的时候仔细检查并修复所有的拼写错误和拼写错误……草率的问题不太可能引起注意。) -
你是对的。我编辑了我的帖子并添加了 ViewModel....
-
当集合内容发生变化时,不需要在 MusicBasePathList 上引发 PropertyChanged,因为它是同一个集合,它不会在视图上做任何事情。但是你应该在 MusicBasePathList 的设置器中提出 PropertyChanged
-
我不这么认为。当我只是将一些东西添加到集合中时,将永远不会调用 setter。当我创建一个新的 Collection 并将其写入 MusicBasePathList 时,将调用 setter。
标签: c# mvvm uwp inotifypropertychanged