我正在尝试将文本框绑定到公共字符串字段,以过滤wpf列表框中的项目列表。我一直收到这个错误。这是相当简单的设置。代码如下。我觉得代码本身很简单,我不清楚问题出在哪里。感谢帮助!
出于某种原因,我的列表始终为空,它应该最初显示所有状态的名称,然后如果“搜索”框包含文本,则会过滤列表。
System.Windows.Data错误:8:无法将目标值保存回 资源。 BindingExpression:路径= SEARCHTEXT; DataItem ='MainWindowViewModel'(HashCode = 37975124);目标元素是 'TextBox'(Name ='SearchBox'); target属性是'Text'(类型 'String')NullReferenceException:'System.NullReferenceException: 对象引用未设置为对象的实例。
VNode.cs
namespace WpfApplication1
{
public class VNode
{
public string Name { get; set; }
}
}
ObservableObject.cs
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace WpfApplication1
{
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MainWindowViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace WpfApplication1
{
public class MainWindowViewModel : ObservableObject
{
private ObservableCollection<VNode> _vnodes;
public ObservableCollection<VNode> VNodes
{
get { return _vnodes; }
set
{
_vnodes = value;
NotifyPropertyChanged("VNodes");
}
}
private ObservableCollection<VNode> _vnodesfiltered;
public ObservableCollection<VNode> VNodesFiltered
{
get { return _vnodesfiltered; }
set
{
_vnodesfiltered = value;
NotifyPropertyChanged("VNodesFiltered");
}
}
public MainWindowViewModel()
{
VNodes = new ObservableCollection<VNode>();
// data testing
List<string> names = new List<string>() { "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "DistrictofColumbia", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "NewHampshire", "NewJersey", "NewMexico", "NewYork", "NorthCarolina", "NorthDakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "RhodeIsland", "SouthCarolina", "SouthDakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "WestVirginia", "Wisconsin", "Wyoming" };
foreach (string name in names)
{
var node = new VNode();
node.Name = name;
VNodes.Add(node);
}
}
private string _searchText = "";
public string SearchText
{
get { return _searchText; }
set
{
if (value != _searchText)
{
_searchText = value;
VNodesFiltered.Clear();
if (string.IsNullOrWhiteSpace(SearchText))
{
foreach (var node in VNodes)
{
VNodesFiltered.Add(node);
}
}
else
{
foreach (var node in VNodes)
{
if (node.Name.Contains(SearchText))
{
VNodesFiltered.Add(node);
}
}
}
}
}
}
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="200"
WindowStartupLocation="CenterScreen">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<ListBox>
<ListBox.ContextMenu>
<ContextMenu FocusManager.FocusedElement="{Binding ElementName=SearchBox}">
<ContextMenu.Template>
<ControlTemplate>
<Border BorderThickness="2" BorderBrush="sc#1,.1,.1,.1" CornerRadius="4"
Background="sc#1,.05,.05,.05">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Margin="4" MinWidth="150" Name="SearchBox" VerticalAlignment="Center"
Text="{Binding SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</TextBox>
<ListBox Grid.Row="1" MinWidth="150" MaxHeight="300" ItemsSource="{Binding VNodes}">
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Name}" FontWeight="Regular" FontSize="12" />
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Border>
</ControlTemplate>
</ContextMenu.Template>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</Grid>
</Window>
答案 0 :(得分:2)
你没有初始化_vnodesfiltered
TextBox
调用SearchText
的setter。此setter调用VNodesFiltered.Clear();
。但由于_vnodesfiltered
为空,VNodesFiltered
也为空
因此VNodesFiltered.Clear();
会抛出NullPointerException
。
因为与Binding表达式相关的setter会抛出异常,所以它无法将值写入源,这正是异常所说的
&#34;无法将目标值保存到源&#34;。
解决方案是在构造函数中初始化_vnodesfiltered
:
public MainWindowViewModel()
{
VNodes = new ObservableCollection<VNode>();
_vnodesfiltered = new ObservableCollection<VNode>();
// data testing
List<string> names = new List<string>() { "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "DistrictofColumbia", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "NewHampshire", "NewJersey", "NewMexico", "NewYork", "NorthCarolina", "NorthDakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "RhodeIsland", "SouthCarolina", "SouthDakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "WestVirginia", "Wisconsin", "Wyoming" };
foreach (string name in names)
{
var node = new VNode();
node.Name = name;
VNodes.Add(node);
}
}
答案 1 :(得分:0)
您尚未实例化VNodesFiltered
集合 - 它是null
。