绑定到文本框会引发绑定异常错误

时间:2015-12-18 13:22:24

标签: c# wpf xaml

我正在尝试将文本框绑定到公共字符串字段,以过滤wpf列表框中的项目列表。我一直收到这个错误。这是相当简单的设置。代码如下。我觉得代码本身很简单,我不清楚问题出在哪里。感谢帮助!

出于某种原因,我的列表始终为空,它应该最初显示所有状态的名称,然后如果“搜索”框包含文本,则会过滤列表。

enter image description here enter image description here

  

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>

2 个答案:

答案 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