我想用C#进行培训,我创建了一个WPF项目,在其中显示一些人(每个人都有一个名字和一件作品),并通过选择一个字段(“名字”或“作品”)和一个搜索字符串,我会把所有的人都过滤掉。例如,字段是“名称”,字符串是“ tin”,唯一的名字包含“ tin”的人是“ tintin”。我编写了所有程序,但搜索引擎(参数化类的目的是过滤人员)出现空引用错误。
这里是人员类别:
namespace VueEnPremier.Model
{
public class Person : ViewModelBase
{
public string Name { get; set; }
public string Work { get; set; }
}
}
这是我的观点:
<Window
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:VueEnPremier"
xmlns:vm="clr-namespace:VueEnPremier.ViewModel"
xmlns:System="clr-namespace:System;assembly=mscorlib" x:Class="VueEnPremier.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<!--<vm:VMSearchName x:Key="ByName" />
<vm:VMSearchWork x:Key="ByWork"/>-->
<vm:VMSearch x:Key="ByName" NameOfTypeToSearch="Name"/>
<vm:VMSearch x:Key="ByWork" NameOfTypeToSearch="Work"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource Locator}}">
<StackPanel>
<StackPanel x:Name="liste">
<ComboBox x:Name="comboBox" Width="150" HorizontalAlignment="Left" Margin="10,10,0,10"
SelectedItem="{Binding Main.SearchEngine, Mode=OneWayToSource}">
<ComboBoxItem Content="{StaticResource ByName}" HorizontalAlignment="Center" IsSelected="True"/>
<ComboBoxItem Content="{StaticResource ByWork}" HorizontalAlignment="Center"/>
</ComboBox>
<TextBox Text="{Binding Main.ToFind, Mode=OneWayToSource}"></TextBox>
<ItemsControl
ItemsSource="{Binding ElementName=comboBox,Path=SelectedItem.(vm:VMSearch.PersonsFiltered)}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
这是我的搜索引擎:
namespace VueEnPremier.ViewModel
{
public class VMSearch : ViewModelBase
{
public string ToFind { get; set; }
public string NameOfTypeToSearch { get; set; }
public VMSearch(string nameOfTypeToSearch)
{
NameOfTypeToSearch = nameOfTypeToSearch;
}
public VMSearch() { }
protected List<Person> Persons { set; get; }
public void UpdatesDatas(List<Person> persons, string toFind)
{
Persons = persons;
ToFind = toFind;
RaisePropertyChanged(() => this.PersonsFiltered);
}
public override string ToString() => NameOfTypeToSearch;
public List<Person> PersonsFiltered
{
get
{
return Persons?.Where(c => (c.GetType().GetProperty(NameOfTypeToSearch).GetValue(c,null) as string).Contains(ToFind)).ToList();
}
}
}
}
PersonsFiltered的getter有点棘手,它从此属性的字符串名称中获取属性的值(“ Name”-> c.Name已获得)。关键是,在XAML中,组合框直接包含2个搜索引擎,并且selectedItem属性应该绑定(一种获取源的方式)到viewmodel的SearchEngine属性:所有逻辑都位于绑定中。
最后是我的视图模型:
using System.Collections.Generic;
using System.Windows.Documents;
using System.Windows.Media.Animation;
using GalaSoft.MvvmLight;
using VueEnPremier.Model;
namespace VueEnPremier.ViewModel
{
/// <summary>
/// This class contains properties that the main View can data bind to.
/// <para>
/// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
/// </para>
/// <para>
/// You can also use Blend to data bind with the tool's support.
/// </para>
/// <para>
/// See http://www.galasoft.ch/mvvm
/// </para>
/// </summary>
public class MainViewModel : ViewModelBase
{
public List<Person> AllNames { get; set; }
#region ToFind
private string _toFind = string.Empty;
public string ToFind
{
get => _toFind;
set
{
_toFind = value;
RaisePropertyChanged(()=>this.ToFind);
SearchEngine.UpdatesDatas(AllNames,value);
}
}
#endregion
#region SearchEngine
private VMSearch _searchEngine;
public VMSearch SearchEngine
{
get { return _searchEngine; }
set
{
if (value != _searchEngine)
_searchEngine = value;
RaisePropertyChanged("SearchEngine");
}
}
#endregion
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
////if (IsInDesignMode)
////{
//// // Code runs in Blend --> create design time data.
////}
////else
////{
//// // Code runs "for real"
////}
Fill();
}
private void Fill()
{
AllNames = new List<Person>();
AllNames.Add(new Person() {Name = "sanzot", Work = "boucher"});
AllNames.Add(new Person() {Name = "buck dany", Work = "pilote"});
AllNames.Add(new Person() {Name = "lefuneste", Work = "cuistre"});
AllNames.Add(new Person() {Name = "tintin", Work = "reporter"});
AllNames.Add(new Person() {Name = "blake", Work = "pilote"});
}
}
}
我使用MVVM灯。我得到的错误是,在启动时:
System.NullReferenceException HResult = 0x80004003消息= La对象的实例的正确性。来源= VueEnPremier采购程序的树莓派:àVueEnPremier.ViewModel.MainViewModel.set_ToFind(String value)dansC:\ Users \ osain \ source \ repos \ MVVMBook \ VueEnPremier \ ViewModel \ MainViewModel.cs:ligne 38
它说的是'searchEngine.updateDatas(AllNames,value);' searchEngine变量为null。
谢谢。
它可能需要UpdateSourceTrigger=PropertyChange
<ComboBox x:Name="comboBox" Width="150" HorizontalAlignment="Left" Margin="10,10,0,10"
SelectedItem="{Binding Main.SearchEngine, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChange}">