2015-12-18 3 views
1

Я пытаюсь связать текстовое поле с открытым строковым полем, чтобы отфильтровать список элементов в списке wpf. Я продолжаю получать эту ошибку. Это довольно простая настройка. Код ниже. Я чувствую, что сам код довольно прост, и я не знаю, где проблема. Помощь приветствуется!Связывание с текстовым полем, вызывающим ошибку исключения связывания

По какой-то причине мой список всегда пуст, и он должен сначала отображать имена всех государств, а затем, если в поле «Поиск» содержится текст, он фильтрует список.

enter image description here enter image description here

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> 
+2

'VNodesFiltered', вероятно,« null ». –

+0

1) VNodesFiltered - null. 2) Вы не реализовали INotifyPropertyChanged в классе vNode. 3) Вместо очистки VNodesFiltered вы можете изменить его на CollectionViewSource и применить фильтр, хотя и предикат, так что при изменении на SearchText вам потребуется только обновить. – user1672994

ответ

2

Вы не инициализируете _vnodesfiltered.
TextBox вызывает установщик SearchText. Этот сеттер вызывает VNodesFiltered.Clear();. Но так как _vnodesfiltered - null, VNodesFiltered - также null.
Поэтому VNodesFiltered.Clear(); throws a NullPointerException.

Поскольку сеттер отношение к Binding выражения бросает исключение, он не может записать значение источника, который является именно то, что говорит исключение с

"Cannot save value from target back to source".

Раствор для инициализации _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); 
    } 
} 
+0

Вы пригвоздили его. Спасибо Domysee! Я совсем забыл запустить эту коллекцию. Хороший быстрый улов с вашей стороны. – JokerMartini

0

Вы не экземпляр VNodesFiltered коллекции - это null.

Смежные вопросы