更改具有双向绑定的控件属性

时间:2020-10-16 15:05:03

标签: c# .net wpf mvvm binding

我有一个带有bool属性的自定义控件。该属性通过Popup绑定包含模板控件。

XAML控件:

<controls:AutoCompleteTextBox x:Name="PART_Editor"
                              IsEnabled="False"
                              IsPopupOpen="{Binding IsAutocompletePopupOpen}" />

控件中的属性:

        public bool IsPopupOpen
        {
            get => (bool)GetValue(IsPopupOpenProperty);
            set => SetValue(IsPopupOpenProperty, value);
        }

        public static readonly DependencyProperty IsPopupOpenProperty =
            DependencyProperty.Register("IsPopupOpen", typeof(bool), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

绑定到包含在模板控件中的元素

<Popup x:Name="PART_AutoCompletePopup"
       IsOpen="{Binding IsPopupOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />

我需要单击更改属性IsPopupOpen。我决定在行为上这样做,但我需要禁用控件。因此,我将行为添加到控件容器中

<Grid>
    <controls:AutoCompleteTextBox x:Name="PART_Editor"
                                  IsEnabled="False"
                                  IsPopupOpen="{Binding IsAutocompletePopupOpen}"/> 
    <i:Interaction.Behaviors>
        <behaviors:PopupContainerBehavior IsPopupOpen="{Binding IsAutocompletePopupOpen, Mode=TwoWay}" />
    </i:Interaction.Behaviors>
</Grid>

行为代码:

public class PopupContainerBehavior : Behavior<UIElement>
    {
        public bool IsPopupOpen
        {
            get { return (bool)GetValue(IsPopupOpenProperty); }
            set { SetValue(IsPopupOpenProperty, value); }
        }

        public static readonly DependencyProperty IsPopupOpenProperty =
            DependencyProperty.Register("IsPopupOpen", typeof(bool), typeof(PopupContainerBehavior), new PropertyMetadata(false));


        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.PreviewMouseLeftButtonDown += OnMouseLeftButtonUp;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            AssociatedObject.PreviewMouseLeftButtonDown -= OnMouseLeftButtonUp;
        }

        private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            IsPopupOpen = true;
        }
    }

问题是该属性首先变为true,然后立即变为false。通过SNOOP,您可以通过该属性的闪烁值看到它。我认为问题出在TwoWay绑定中,但我不知道如何修复

1 个答案:

答案 0 :(得分:1)

发生这种情况的原因是由于鼠标捕获。

  • 行为的PreviewMouseLeftButtonDown事件处理程序告诉Popup打开
  • 弹出窗口捕获鼠标
  • 其余的点击事件会触发容器
  • 容器从Popup
  • 中夺走了鼠标
  • Popup立即关闭

这可能是一个棘手的问题。

您可能要考虑使您的控件在Popup被禁用时能够打开,而不是从外部尝试打开。即使控件被禁用,也可以通过在需要交互的部分上设置IsHitTestVisible来使它的一部分可单击。

相关问题