【发布时间】:2017-10-06 21:11:40
【问题描述】:
我试图在初始化时和初始化时对 ListView 使用过滤器,但该项目正在为 ListView 抛出一个空指针,即使我在构造函数和绑定中设置它。这是我的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var viewModel = new MainViewModel();
this.ProjectListView.ItemsSource = viewModel.Projects;
这里是引用它的 XAML。
<ListView x:Name="ProjectListView" Margin="0,0,10,0" ItemsSource="{Binding Projects}" FontSize="16" Foreground="Black">
如果在构造函数中初始化,我不确定为什么 ItemSource 为空。我需要应用 PropertyChanged 绑定吗?
这是我的大部分 XAML
<TextBox x:Name="FolderNameBox" Grid.Column="1" Background="White" Grid.Row="1" Grid.ColumnSpan="5"
Margin="0,0,287,654.333" VerticalContentAlignment="Center"
Padding="6" FontSize="16"
IsReadOnly="True"
Text="{Binding ElementName=Hierarchy, Path=SelectedItem.Path, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}">
</TextBox>
<TextBox x:Name="SearchProjectsBox" Grid.Column="5" Background="White" Grid.Row="1" Text="Search Projects"
Margin="47.333,0,0,654.333" VerticalContentAlignment="Center" Foreground="LightGray" Padding="6" FontSize="16" HorizontalAlignment="Left" Width="268" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" TextChanged="FilterListView"/>
<TreeView x:Name="Hierarchy" Grid.Column="4" HorizontalAlignment="Left" Height="631" Margin="0,58,0,0" Grid.Row="1" VerticalAlignment="Top" Width="226"
ItemsSource="{Binding Path=Projects}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ChildFolders}">
<StackPanel Orientation="Horizontal" >
<Image Source="{Binding Icon}" Margin="5, 5, 5, 5"></Image>
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" BorderThickness="0" FontSize="16" Margin="5" IsReadOnly="True" PreviewMouseDoubleClick="SelectAll" LostFocus="TextBoxLostFocus"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<Grid Grid.ColumnSpan="2" Grid.Column="4" HorizontalAlignment="Left" Height="631" Margin="245,58,0,0" Grid.Row="1" VerticalAlignment="Top" Width="540">
<ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<ListView x:Name="ProjectListView" Margin="0,0,10,0" ItemsSource="{Binding Projects}" FontSize="16" Foreground="Black">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="false">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
这是我的基本视图模型
private ObservableCollection<Project> projects;
public ObservableCollection<Project> Projects
{
get { return projects; }
set
{
if (value != projects)
{
projects = value;
OnPropertyChanged("Projects");
}
}
}
这是背后的代码
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
MainViewModel model = new MainViewModel();
model.BuildData();
this.ProjectListView.ItemsSource = model.Projects;
}
private void FilterListView(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView(this.ProjectListView.ItemsSource).Refresh();
}
FilterListView 是 TextChange 方法。它在第一行中断。 ProjectListVIew 注册为 null,但它甚至不应该启动,因为它依赖于 TextBox 中的更改。
编辑。这是后面的代码
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
MainViewModel model = new MainViewModel();
model.BuildData();
this.ProjectListView.ItemsSource = model.Projects;
}
private void FilterListView(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView(this.ProjectListView.ItemsSource).Refresh();
}
private void SelectAll(object sender, MouseButtonEventArgs e)
{
TextBox box = sender as TextBox;
box.IsReadOnly = false;
box.SelectAll();
}
private void TextBoxLostFocus(object sender, RoutedEventArgs e)
{
TextBox box = sender as TextBox;
box.IsReadOnly = true;
}
private void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox tb = (TextBox)sender;
tb.Text = string.Empty;
tb.Foreground = Brushes.Black;
tb.GotFocus -= TextBox_GotFocus;
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
TextBox box = (TextBox)sender;
box.Text = "Search Projects";
box.Foreground = Brushes.LightGray;
box.GotFocus += TextBox_GotFocus;
}
}
}
基础视图模型
public class ViewModelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string projectName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(projectName));
}
}
#endregion INotifyPropertyChanged
}
以及我正在使用的视图模型
class MainViewModel : ViewModelBase
{
private ObservableCollection<Project> projects;
public ObservableCollection<Project> Projects
{
get { return projects; }
set
{
if (value != projects)
{
projects = value;
OnPropertyChanged("Projects");
}
}
}
编辑:
我的 ListView 不断变化 - 例如,显示的数据将基于用户在 TreeView 中的选择。现在,我的过滤器没有考虑屏幕上的实际内容。它仅基于绑定的集合进行过滤。
因此,如果我的集合是水果、蔬菜、肉类、乳制品,而我的 ListView 是 Apple、Carrot 和 Milk,如果我搜索 Apple,ListView 将为空白,但如果我搜索 Fruit,我将有一个填充的行。显然不正确。
听起来我很接近。
这是我的视图模型:
public ICollectionView SourceCollection
{
get
{
return this.projectCollection.View;
}
}
public string FilterText
{
get
{
return filterText;
}
set
{
filterText = value;
this.projectCollection.View.Refresh();
RaisePropertyChanged("SearchProjectsText");
}
}
private void projectCollection_Filter(object sender, FilterEventArgs e)
{
if (string.IsNullOrEmpty(FilterText))
{
e.Accepted = true;
return;
}
Project project = e.Item as Project;
if (project.Name.ToUpper().Contains(FilterText.ToUpper()) || project.Path.ToUpper().Contains(FilterText.ToUpper()))
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
public void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
其中 SearchProjectText 是用于过滤的实际文本框。我的相关 XAML:
<TextBox x:Name="SearchProjectsBox" Grid.Column="5" Background="White" Grid.Row="1" Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"
Margin="47.333,0,0,654.333" VerticalContentAlignment="Center" Foreground="Black" Padding="6" FontSize="16" HorizontalAlignment="Left" Width="268"/>
<TreeView x:Name="Hierarchy" Grid.Column="4" HorizontalAlignment="Left" Height="631" Margin="0,58,0,0" Grid.Row="1" VerticalAlignment="Top" Width="226"
ItemsSource="{Binding Path=Projects}">
<ListView x:Name="ProjectListView" Margin="0,0,10,0" ItemsSource="{Binding SourceCollection}" FontSize="16" Foreground="Black">
【问题讨论】:
-
您正在更新
MainViewModel,但viewModel.Projects可能仍然是null?