如果从 DataTrigger 更改绑定,双向绑定将不起作用

TwoWay Binding is not working if Binding is changed from DataTrigger

我的工具栏项有以下数据模板:

<DataTemplate DataType="{x:Type viewModels:PopupContextActionViewModel}">
   <Grid>
      <ToggleButton Name="ToggleButton">
         <ContentControl Template="{Binding Icon, Converter={StaticResource NameToResourceConverter}}" Margin="5" />
      </ToggleButton>
      <Popup Name="ContextActionPopup" StaysOpen="False" AllowsTransparency="True"
         IsOpen="{Binding 
            ElementName=ToggleButton, 
            Path=IsChecked, 
            Mode=TwoWay, 
            UpdateSourceTrigger=PropertyChanged}">
         <Border Background="Transparent" Name="Border" Visibility="Visible">
            <ContentControl x:Name="ContentControl" userInterface:RegionHelper.RegionName="{Binding RegionId}" Style="{StaticResource PopupContentStyle}" />
         </Border>
      </Popup>
   </Grid>
   <DataTemplate.Triggers>
      <Trigger SourceName="ContentControl" Property="Content" Value="{x:Null}">
         <Setter TargetName="ContextActionPopup" Property="IsOpen" Value="False" />
      </Trigger>
   </DataTemplate.Triggers>

一切正常(我的弹出窗口和我的切换按钮确实可以正常工作)但是如果我设置我的 DataTemplate 的触发器的值(这是由我的业务逻辑完成的,或者更具体地说是由一些 "NavigationService") 弹出窗口关闭,而切换按钮保持选中状态。

为什么我的触发器不更改我的 ToggleButton 的 IsChecked 属性?

您的答案可以在 MSDN 的 Dependency Property Value Precedence 页面中找到。简而言之,您在 IsOpen 属性 上设置了一个本地值,该值的优先级高于 Trigger 设置的值。解决方法是 不是 设置本地值,而是在 Style 中设置初始值,它的优先级低于 Trigger.

来自 MSDN 上的链接页面:

The following is the definitive order that the property system uses when assigning the run-time values of dependency properties. Highest precedence is listed first. This list expands on some of the generalizations made in the Dependency Properties Overview.

  1. Property system coercion. For details on coercion, see Coercion, Animation, and Base Value later in this topic.

  2. Active animations, or animations with a Hold behavior. In order to have any practical effect, an animation of a property must be able to have precedence over the base (unanimated) value, even if that value was set locally. For details, see Coercion, Animation, and Base Value later in this topic.

  3. Local value. A local value might be set through the convenience of the "wrapper" property, which also equates to setting as an attribute or property element in XAML, or by a call to the SetValue API using a property of a specific instance. If you set a local value by using a binding or a resource, these each act in the precedence as if a direct value was set.

  4. TemplatedParent template properties. An element has a TemplatedParent if it was created as part of a template (a ControlTemplate or DataTemplate). For details on when this applies, see TemplatedParent later in this topic. Within the template, the following precedence applies:

a.Triggers from the TemplatedParent template.

b.Property sets (typically through XAML attributes) in the TemplatedParent template.

  1. Implicit style. Applies only to the Style property. The Style property is filled by any style resource with a key that matches the type of that element. That style resource must exist either in the page or the application; lookup for an implicit style resource does not proceed into the themes.

  2. Style triggers. The triggers within styles from page or application (these styles might be either explicit or implicit styles, but not from the default styles, which have lower precedence).

  3. Template triggers. Any trigger from a template within a style, or a directly applied template.

  4. Style setters. Values from a Setter within styles from page or application.

  5. Default (theme) style. For details on when this applies, and how theme styles relate to the templates within theme styles, see Default (Theme) Styles later in this topic. Within a default style, the following order of precedence applies:

a.Active triggers in the theme style.

b.Setters in the theme style.

  1. Inheritance. A few dependency properties inherit their values from parent element to child elements, such that they need not be set specifically on each element throughout an application. For details see Property Value Inheritance.

  2. Default value from dependency property metadata. Any given dependency property may have a default value as established by the property system registration of that particular property. Also, derived classes that inherit a dependency property have the option to override that metadata (including the default value) on a per-type basis. See Dependency Property Metadata for more information. Because inheritance is checked before default value, for an inherited property, a parent element default value takes precedence over a child element. Consequently, if an inheritable property is not set anywhere, the default value as specified on the root or parent is used instead of the child element default value.