CheckBox Checked事件在绑定集合更新之前触发

时间:2017-07-06 09:25:24

标签: c# silverlight data-binding

我有一个自定义控件来显示带ComboBox内复选框的项目。要实现这一点,我使用DataTemplateCheckBoxItemSource的{​​{1}}使用绑定到包含我的过滤器值的ComboBoxObserableCollection<FilterValue>是一个实现FilterValue的自定义类。 INotifyPropertyChanged的属性ContentIsChecked也使用绑定来使用我的列表的值。此控件将在Silverlight中使用。

绑定本身工作正常,如下所示:
Binding itself works fine, as seen here:

当我注册CheckBoxChecked事件时,会出现问题。

只要其中一个复选框更改了其状态,就会按预期触发事件,但此时,绑定列表中的值仍未更新。 我在调试时看到的是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>

1 个答案:

答案 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

在该事件处理程序中,您将正确地看到正确的行为。