【发布时间】:2016-02-18 21:43:52
【问题描述】:
我是 WPF 新手,我在现有设置中遇到了一些问题,无法让列表框选定项出现在文本框中。
这里的图片代表了问题。我在文本框中输入了“12 HOUR”,然后将列表框过滤到字符串中任何位置带有“12 HOUR”的项目。但是当我点击列表框中的“12 Hour Nasal”时,我现在想在文本框中反映该选择:
http://i.imgur.com/ZCYAolT.png
这是包含列表框和文本框的用户控件的 XAML:
<UserControl x:Class="SCM_AllergyRecModule.SearchAndSelectView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<StackPanel Width="300">
<TextBox x:Name="Filter" Text="{Binding Path=Filter, UpdateSourceTrigger=PropertyChanged}"/>
<ListBox Width ="300" Height="50" x:Name="ListBoxControl"
ItemsSource="{Binding Path=Allergens}"
SelectedItem="{Binding Path=SelectedAllergen}">
</ListBox>
</StackPanel>
这里是 ViewModel:
namespace SCM_AllergyRecModule
{
public class SearchAndSelectViewModel
{
private ICollectionView allergens;
private string selectedAllergen;
private string filter = "";
public string Filter
{
get
{
return this.filter.ToUpperInvariant();
}
set
{
if (this.filter != value)
{
this.filter = value;
this.Allergens.Refresh();
}
}
}
private bool ContainsFilter(object item)
{
var product = item as string;
if (product == null)
{
return false;
}
if (string.IsNullOrEmpty(this.Filter))
{
return true;
}
if (product.ToUpperInvariant().Contains(this.Filter))
{
return true;
}
return false;
}
public SearchAndSelectViewModel()
{
var cvs = new CollectionViewSource();
cvs.Source = MainWindow.scmAllergens;
this.allergens = cvs.View;
this.allergens.Filter = ContainsFilter;
}
public ICollectionView Allergens
{
get
{
return this.allergens;
}
}
public string SelectedAllergen
{
get
{
return this.selectedAllergen;
}
set
{
if (this.selectedAllergen != value)
{
this.selectedAllergen = value;
}
}
}
}
}
更新 1
我将 INotifyPropertyChanged 接口添加到我的类中,并在 setter 中的 SelectedAllergen 上引发它。我添加了一个名为 SearchAndSelectViewModel_PropertyChanged 的事件处理程序来处理 SelectedAllergen 属性更改并将其设置在构造函数中。
现在,当我单击列表框中的一个项目时,我确实看到它将过滤器设置为 SelectedItem,而列表过滤器设置为该项目,因此没有其他内容显示。但是,文本框文本仍然没有改变?请参阅下面的屏幕截图。这是在我在文本框中输入“PEAN”之后,然后列表框过滤为两个选项,然后我选择了“PEANUTS (FOOD)”,然后重新过滤列表框以仅显示该选项但未设置文本框到“花生(食物)”:
更新的视图模型
public class SearchAndSelectViewModel : INotifyPropertyChanged
{
private ICollectionView allergens;
private string selectedAllergen;
private string filter;
public string Filter
{
get
{
return this.filter.ToUpperInvariant();
}
set
{
if (this.filter != value)
{
this.filter = value;
this.Allergens.Refresh();
}
}
}
private bool ContainsFilter(object item)
{
var product = item as string;
if (product == null)
{
return false;
}
if (string.IsNullOrEmpty(this.Filter))
{
return true;
}
if (product.ToUpperInvariant().Contains(this.Filter))
{
return true;
}
return false;
}
private void SearchAndSelectViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "SelectedAllergen":
this.Filter = this.SelectedAllergen;
break;
}
}
public SearchAndSelectViewModel()
{
filter = "";
var cvs = new CollectionViewSource();
cvs.Source = MainWindow.scmAllergens;
this.allergens = cvs.View;
this.allergens.Filter = ContainsFilter;
this.PropertyChanged += SearchAndSelectViewModel_PropertyChanged;
}
public ICollectionView Allergens
{
get
{
return this.allergens;
}
}
public string SelectedAllergen
{
get
{
return this.selectedAllergen;
}
set
{
if (this.selectedAllergen != value && value != null)
{
this.selectedAllergen = value;
OnPropertyChanged("SelectedAllergen");
}
}
}
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
【问题讨论】:
-
当
SelectedAllergen被设置时,为什么不也设置你的Filter? (但可能需要更好的机制,因为您在 setter 中有一些业务逻辑)。看起来您也缺少INotifyPropertyChanged。视图没有任何东西可以用来监听属性值的变化。 -
或者你可以简单地监听 listbox 上的 selectionchanged 事件并设置过滤器值´
标签: c# wpf xaml mvvm user-controls