我无法在WPF中重复使用用户控件,我希望你能提供帮助。
在运行时,我正在创建此用户控件的新实例以显示在WPF网格中。用户控件由文本框和列表框组成,其中文本框中的用户输入过滤列表框中的结果。比如说这个例子,我在运行时动态地创建了两个相同的用户控件,共享相同的ViewModel。但是,当我运行应用程序时,如果我在第二个用户控件文本框中输入内容,它会反映在用户控件的两个列表框中。我只希望它反映在自己的列表框中。
以下是前端问题的图片。突出显示的输入反映在两个列表框中,但不应该:
以下是用户控件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="150">
<TextBox x:Name="Filter" Text="{Binding Path=Filter, UpdateSourceTrigger=PropertyChanged}"/>
<ListBox Height="50"
ItemsSource="{Binding Path=Allergens}"
IsSynchronizedWithCurrentItem="True"
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()
{
this.allergens = CollectionViewSource.GetDefaultView(MainWindow.scmAllergens);
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;
}
}
}
}
}
以下是主窗口中运行时用户控件的动态加载(请暂时忽略命名):
SearchAndSelectView ssvAllergenSearch = new SearchAndSelectView();
ssvAllergenSearch.DataContext = new SearchAndSelectViewModel();
controlName = "ssvAllergenSearch" + (rowCounter.ToString() + allergenColumn.ToString());
ssvAllergenSearch.Name = controlName;
this.RegisterName(controlName, cmbAllscriptsCategory);
Grid.SetRow(ssvAllergenSearch, rowCounter);
Grid.SetColumn(ssvAllergenSearch, allergenColumn);
DynamicGrid.Children.Add(ssvAllergenSearch);
答案 0 :(得分:1)
我认为这是违规行:
this.allergens = CollectionViewSource.GetDefaultView(MainWindow.scmAllergens);
我假设您只有一个MainWindow实例,因此只有一个scmAllergens实例。通过调用CollectionViewSource.GetDefaultView
,您将获得相同的CollectionViewSource
次。改为手动创建一个新实例:
var cvs = new CollectionViewSource();
cvs.Source = MainWindow.scmAllergens;
this.allergens = cvs.View;
答案 1 :(得分:1)
如果他们共享相同的视图模型,那就是您的问题。您的控件被DataContext绑定到同一个源,因此目标链接回同一个实例,这导致一个更改通过双向绑定更改另一个。为每个实例化单独的模型,您的问题将得到解决。将控件构建为具体控件(代码隐藏也是视图模型)可以消除此问题,并且在大多数情况下是MVVM最佳实践。