简体   繁体   中英

Binding to a textbox throws bind exception error

I'm trying to bind a textbox to a public string field to filter a list of items in the wpf listbox. I keep getting this error. It's rather simple setup. The code is below. I feel that the code itself is rather simple and I'm not clear as to where the problem is. Help is appreciated!

For some reason my list is always empty and it should initially display the names of all the States, and then if the Search box contains text it filters the list.

在此处输入图片说明 在此处输入图片说明

System.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=SearchText; DataItem='MainWindowViewModel' (HashCode=37975124); target element is 'TextBox' (Name='SearchBox'); target property is 'Text' (type 'String') NullReferenceException:'System.NullReferenceException: Object reference not set to an instance of an object.

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>

You dont initialize _vnodesfiltered .
The TextBox invokes the setter of SearchText . This setter calls VNodesFiltered.Clear(); . But since _vnodesfiltered is null, VNodesFiltered is also null.
Therefore VNodesFiltered.Clear(); throws a NullPointerException .

Because the setter relevant for the Binding expression throws an exception, it cannot write the value to the source, which is exactly what the exception says with

"Cannot save value from target back to source".

The solution is to initialize _vnodesfiltered in your constructor:

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);
    }
}

您尚未实例化VNodesFiltered集合-它为null

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM