我有一个自定义控件来显示带ComboBox
内复选框的项目。要实现这一点,我使用DataTemplate
和CheckBox
。 ItemSource
的{{1}}使用绑定到包含我的过滤器值的ComboBox
。 ObserableCollection<FilterValue>
是一个实现FilterValue
的自定义类。 INotifyPropertyChanged
的属性Content
和IsChecked
也使用绑定来使用我的列表的值。此控件将在Silverlight中使用。
当我注册CheckBox
或Checked
事件时,会出现问题。
只要其中一个复选框更改了其状态,就会按预期触发事件,但此时,绑定列表中的值仍未更新。
我在调试时看到的是Unchecked
/ Checked
事件在Unchecked
的{{1}}事件之前触发。
这意味着在事件发生时,我无法向列表询问所有活动(已选中)过滤器。我能做些什么来实现这个目标?
FilterControl.xaml:
PropertyChanged
FilterControl.xaml.cs:
FilterValue
FilterValue:
<UserControl
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:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:local="clr-namespace:Controls" x:Class="Controls.FilterControl"
mc:Ignorable="d"
d:DesignHeight="45" d:DesignWidth="140">
<StackPanel x:Name="LayoutRoot">
<sdk:Label x:Name="LblFilterDescription" Content="-" />
<ComboBox x:Name="Filter" Width="120" ItemsSource="{Binding AvailableFilters, RelativeSource={RelativeSource FindAncestor, AncestorType=local:FilterControl}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Path=Text}" IsChecked="{Binding Path=IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Checked="FilterChanged" Unchecked="FilterChanged" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</UserControl>
答案 0 :(得分:2)
因此,当我尝试重现此行为时,我意识到这似乎只是像Silverlight中那样发生的行为。如果您在WPF上尝试此示例,{/ 1}}会在更新绑定属性后触发。因此,您只需使用Changed
方法访问AppliedFilters
属性,它就会反映实际的当前情况。但是在Silverlight上,并没有那么多。更糟糕的是,这种行为对我来说似乎并不一致。我确实遇到了事件在属性更新后触发的情况(导致预期的输出)。
解决这个问题的方法是清理组件逻辑。如果你看一下,你会混合两个不同的概念:事件驱动的UI逻辑和清晰的数据绑定。当然,“正确”执行它会产生多种影响,你可能无法在现有项目中确保这种影响,但你至少可以尝试在这里找到正确的方向,这也应该解决这个问题。
因此,您的逻辑现在使用数据绑定为视图提供数据,并反映所显示项目的更改。但是,您正在使用项目级别的事件来执行其他逻辑,具体取决于以前的更改。正如我们所看到的,跨平台不能保证执行的顺序,因此最好避免不得不依赖它。
在这种情况下,您应该将数据作为事实的来源,并且在应用过滤器更改时,数据中的更改会告诉您。通过FilterChanged
和实施ObservableCollection
的项目,您已经到了一半。不幸的是,可观察集合只会通知您有关集合的更改,但不会通知您对所包含项目的更改。但是有多种解决方案可以扩展集合以查看集合中的项目。
This related question完全涵盖了该主题,并且关于如何针对该行为扩展可观察集合有多种想法。就我而言,我使用了FullyObservableCollection
implementation by Bob Sammers。
您需要做的就是将INotifyPropertyChanged
更改为ObservableCollection<FilterValue>
并订阅FullyObservableCollection<FilterValue>
事件:
ItemPropertyChanged
在该事件处理程序中,您将正确地看到正确的行为。