WPF数据绑定:CollectionViewSource和ObjectDataProvider问题
-
29-09-2019 - |
题
我有一个mainwindow.xaml文件:
<Window.Resources>
<CollectionViewSource x:Key="cvs"
Source="{Binding Source={StaticResource ResourceKey=DetailsCollection}}" />
<CollectionViewSource x:Key="DetailScopes">
<CollectionViewSource.Source>
<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="entities:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</CollectionViewSource.Source>
</CollectionViewSource>
<DataTemplate x:Key="AccountDetail"
DataType="{x:Type entities:AccountDetail}">
<DockPanel>
<ComboBox
DockPanel.Dock="Left"
ItemsSource="{Binding Source={StaticResource ResourceKey=DetailScopes}}"
SelectedItem="{Binding Path=Scope}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Converter={StaticResource DetailScopeConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Text="{Binding Path=Value}" />
</DockPanel>
</DataTemplate>
</Window.Resources>
...
<ListBox
ItemTemplate="{StaticResource ResourceKey=AccountDetail}"
ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}" />
及其代码范围类,我在其中定义了详细信息范围的过滤器:
public class MainWindow
{
public MainWindow()
{
CollectionViewSource detailScopes;
InitializeComponent();
// Attach filter to the collection view source
detailScopes = this.Resources["DetailScopes"] as CollectionViewSource;
detailScopes.Filter += new FilterEventHandler(DetailScopesFilter);
private void DetailScopesFilter(object sender, FilterEventArgs e)
{
DetailScope scope;
scope = (DetailScope)e.Item;
if (scope == DetailScope.Private ||
scope == DetailScope.Business)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
}
}
接下来,有 AccountDetail
班级:
public class AccountDetail
{
public string Value
{
get { return this.value; }
set { this.value = value; }
}
public DetailScope Scope
{
get { return scope; }
set { scope = value; }
}
private string value;
private DetailScope scope;
}
最后,一个枚举:
public enum DetailScope
{
Private,
Business,
Other
}
当我运行代码时,我将获得一个带有大量帐户详细信息的列表框,每个列表都有自己的组合框,带有选定的示波器和一个带有适当值的文本框。问题在于,组合框中的所有选定值都匹配了最后输入的详细信息的范围集,并更改了所有组合框值更新所有这些值,就好像它们都绑定到同一帐户详细信息一样。
当我取出 ObjectDataProvider
来自 CollectionViewSource
详细信息并将其直接绑定到组合框 ItemsSource
在里面 DataTemplate
帐户尾尾,问题已经消失。但是,我确实需要它 CollectionViewSource
因为我正在对其进行一些过滤,所以我无法将过滤应用于 ObjectDataProvider
.
有人可以解释为什么会发生这种情况,以及我实际上应该如何联系 CollectionViewSource
和 ObjectDataProvider
?谢谢你。
解决方案
.
您的代码问题是 每个组合都使用CollectionViewSource的相同实例;这意味着,具有关键“详细信息”的资源是 由所有人共享 Combobox,因此,每当您从特定的ComboBox中选择一个值时,它都会在所有ComboBox中自动选择相同的值。 这是因为共享的基础集合可以跟踪所选项目,并且由于它从一个ComboBox选择时进行了更改,因此CollectionViewSource通知了所有ComboBox的更改.
因此解决方案非常简单。您需要进行详细信息资源 不可出现.
这是解决方案:
<!-- Please note this x:Shared="False" just after x:Key="DetailsScopes" --->
<CollectionViewSource x:Key="DetailScopes" x:Shared="False">
<CollectionViewSource.Source>
<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="entities:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</CollectionViewSource.Source>
</CollectionViewSource>
希望它能解决您的问题!
但是,该解决方案将引起另一个问题。让我引用MSDN的内容,以便您了解x:共享的作用。
X:共享属性
设置为false时,修改了WPF资源 - 回归行为,以便请求属性资源 为每个请求创建一个新实例 而不是为所有请求共享相同的实例。
由于x:共享的原因是在您尝试访问时创建资源的新实例(新副本),这意味着,过滤器处理程序方法仅附加到您在代码中获得的实例,而不是所有的实例实例。
因此,为了正确处理处理程序,您需要从XAML本身附加处理程序,例如:
<!-- Now please note Filter="DetailsScopesFilter" --->
<CollectionViewSource x:Key="DetailScopes" x:Shared="False" Filter="DetailScopesFilter">
<CollectionViewSource.Source>
<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="entities:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</CollectionViewSource.Source>
</CollectionViewSource>
希望它能解决您的所有问题。让我知道您是否仍然面对任何东西。:-)
哦,顺便说一句,不再需要以下代码。所以请删除它。
// Attach filter to the collection view source
detailScopes = this.Resources["DetailScopes"] as CollectionViewSource;
detailScopes.Filter += new FilterEventHandler(DetailScopesFilter);
.