将 Textbox IsFocused 绑定到 Popup IsOpen 以及附加条件

发布于 2024-07-19 10:54:08 字数 2968 浏览 2 评论 0原文

我有一个 TextBox 和一个 Popup 控件。 我希望将 Popup.IsOpen 属性绑定到 TextBox.IsFocused 属性。 换句话说,如果文本框具有焦点,则弹出窗口打开。 或者,如果弹出窗口处于焦点状态,我不希望它由于文本框失去焦点而关闭。 我希望使用绑定来处理这个问题,而不是在事件处理程序中处理这个问题。 另外,我是否必须对依赖属性执行任何操作,因为它们是预先存在的(即注册、覆盖元数据等),或者我可以只绑定到这些属性吗?

下面是一些与我的场景类似的示例代码

StackPanel sp = new StackPanel();
TextBox tb = new TextBox();
Popup popup = new Popup();

sp.Children.Add(tb);
sp.Children.Add(popup);
this.Content = sp;

Binding bd = new Binding("IsFocused");
bd.source = tb.IsFocused;
popup.SetBinding(Popup.IsOpenProperty, bd);

,我假设如果单击文本框控件并为其提供焦点,则弹出窗口将打开,反之,如果文本框失去焦点,则弹出窗口将关闭。 我似乎无法让它发挥作用。

如果有人知道我做错了什么,那么也许他们也可以回答我问题的后半部分,即如果文本框失去焦点但弹出窗口接收焦点,则弹出窗口将保持打开状态或重新获得焦点到文本框,以便它在第一个绑定之后保持打开状态。 当文本框失去焦点时获得焦点的任何其他控件不适用于此场景。

如果我可以为了清楚起见重新表述一下,我会这样说。

1.)Popup.IsOpen 绑定到 TextBox.IsFocused

2.) 绑定 TextBox.IsFocused< /code> 到 Popup.IsFocused(假设这只会将焦点返回到文本框)


这是我的第一次 C# 尝试。 有些事情还是不太对劲。 什么也没发生,所以我不太确定我的错误在哪里。

        StackPanel sp = new StackPanel(); 
        TextBox tb = new TextBox(); 
        Popup popup = new Popup();

        TextBox popupTextBox = new TextBox();
        popup.Child = popupTextBox;


        sp.Children.Add(tb); 
        sp.Children.Add(popup); 
        this.Content = sp;


        //***Questions concerning giving the UIElement a name and registering it
        tb.Name = "siblingTextBox";
        System.Windows.NameScope.GetNameScope(tb).RegisterName("siblingTextBox", tb);

        //***Questions concerning giving the UIElement a name and registering it
        popupTextBox.Name = "popupTextBox";
        System.Windows.NameScope.GetNameScope(tb).RegisterName("popupTextBox", popupTextBox);

        Binding binding = new Binding();
        binding.ElementName = tb.Name;
        popup.PlacementTarget = tb;

        Style style = new Style();
        style.TargetType = typeof(Popup);

        DataTrigger dataTrigger = new DataTrigger();
        Binding focusedBinding = new Binding("IsFocused");
        focusedBinding.ElementName = tb.Name;
        dataTrigger.Value = true;
        dataTrigger.Binding = focusedBinding;

        Setter setter = new Setter();
        setter.Property = Popup.IsOpenProperty;
        setter.Value = true;
        dataTrigger.Setters.Add(setter);
        style.Triggers.Add(dataTrigger);

        dataTrigger = new DataTrigger();
        focusedBinding = new Binding("IsFocused");
        focusedBinding.ElementName = popupTextBox.Name;
        dataTrigger.Value = true;
        dataTrigger.Binding = focusedBinding;
        setter = new Setter();
        setter.Property = Popup.IsOpenProperty;
        setter.Value = true;
        dataTrigger.Setters.Add(setter);
        style.Triggers.Add(dataTrigger);

        popup.Style = style;

I have a TextBox and a Popup control. I want the Popup.IsOpen property to be bound to the TextBox.IsFocused property. In other words, if the textbox has focus, the popup is open. Alternatively, if the popup is in focus, I don't want it to close due to the textbox losing focus. I was hoping to handle this using bindings rather than having to deal with this in event handlers. Also, do I have to do anything regarding the dependency properties, since they are pre-existing(i.e. Register, override metadata, etc), or can I just bind to these properties.

Here is some sample code similar to my scenario

StackPanel sp = new StackPanel();
TextBox tb = new TextBox();
Popup popup = new Popup();

sp.Children.Add(tb);
sp.Children.Add(popup);
this.Content = sp;

Binding bd = new Binding("IsFocused");
bd.source = tb.IsFocused;
popup.SetBinding(Popup.IsOpenProperty, bd);

From this I was assuming that if I clicked on the textbox control and gave it focus, that the popup would open, and conversely if the textbox lost focus, that the popup would close. I can't seem to get this to work.

If someone has an idea of what I'm doing wrong, then maybe they could also answer the second half of my question that if the textbox loses focus but it was the popup that receives focus, that the popup will remain open or give focus back to the textbox so that it will remain open bc of the first binding. Any other control that gains focus when the textbox loses focus does not apply to this scenario.

If I could reword this for clarity I would say it like this.

1.) Bind Popup.IsOpen to TextBox.IsFocused

2.) Bind TextBox.IsFocused to Popup.IsFocused(assuming this will just give focus back to the textbox)


Here is my first C# attempt at this. Something is still not quite right. Nothing happens so I'm not quite sure where my mistake is.

        StackPanel sp = new StackPanel(); 
        TextBox tb = new TextBox(); 
        Popup popup = new Popup();

        TextBox popupTextBox = new TextBox();
        popup.Child = popupTextBox;


        sp.Children.Add(tb); 
        sp.Children.Add(popup); 
        this.Content = sp;


        //***Questions concerning giving the UIElement a name and registering it
        tb.Name = "siblingTextBox";
        System.Windows.NameScope.GetNameScope(tb).RegisterName("siblingTextBox", tb);

        //***Questions concerning giving the UIElement a name and registering it
        popupTextBox.Name = "popupTextBox";
        System.Windows.NameScope.GetNameScope(tb).RegisterName("popupTextBox", popupTextBox);

        Binding binding = new Binding();
        binding.ElementName = tb.Name;
        popup.PlacementTarget = tb;

        Style style = new Style();
        style.TargetType = typeof(Popup);

        DataTrigger dataTrigger = new DataTrigger();
        Binding focusedBinding = new Binding("IsFocused");
        focusedBinding.ElementName = tb.Name;
        dataTrigger.Value = true;
        dataTrigger.Binding = focusedBinding;

        Setter setter = new Setter();
        setter.Property = Popup.IsOpenProperty;
        setter.Value = true;
        dataTrigger.Setters.Add(setter);
        style.Triggers.Add(dataTrigger);

        dataTrigger = new DataTrigger();
        focusedBinding = new Binding("IsFocused");
        focusedBinding.ElementName = popupTextBox.Name;
        dataTrigger.Value = true;
        dataTrigger.Binding = focusedBinding;
        setter = new Setter();
        setter.Property = Popup.IsOpenProperty;
        setter.Value = true;
        dataTrigger.Setters.Add(setter);
        style.Triggers.Add(dataTrigger);

        popup.Style = style;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁把谁当真 2024-07-26 10:54:08

下面的代码演示了 StackPanel 中有两个文本框,将焦点设置到顶部文本框将打开 Popup。 此时,如果您将焦点移动到弹出窗口中包含的文本框,它将保持打开状态。 如果将焦点移至另一个元素(在本例中为 StackPanel 中的第二个文本框),弹出窗口将关闭。 由于您无法聚焦弹出窗口本身,我实际上绑定到弹出窗口中文本框的 IsFocused 属性。

<StackPanel>
    <TextBox x:Name="text" Text="This is a text box" />
    <TextBox Text="Another Text Box" />
    <Popup PlacementTarget="{Binding ElementName=text}">
        <Popup.Style>
            <Style TargetType="{x:Type Popup}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=text, Path=IsFocused}" Value="True">
                        <Setter Property="IsOpen" Value="True" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding ElementName=popupText, Path=IsFocused}" Value="True">
                        <Setter Property="IsOpen" Value="True" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Popup.Style>
        <TextBox x:Name="popupText" Text="HELLO WORLD" />
    </Popup>
</StackPanel>

要在 C# 中实现相同的效果,您不必使用 ElementName 绑定,因为您手头上已经有了元素。 我几乎总是使用 XAML 来定义我的元素,因此我确信您可以稍微整理一下。

var text1 = new TextBox { Name = "text", Text = "This is a text box" };
var text2 = new TextBox { Text = "Another Text Box" };
var popupText = new TextBox { Name = "popupText", Text = "HELLO WORLD" };
var popup = new Popup { Child = popupText, PlacementTarget = text1 };
var stackPanel = new StackPanel();

stackPanel.Children.Add(text1);
stackPanel.Children.Add(text2);
stackPanel.Children.Add(popup);

var popupStyle = new Style(typeof (Popup));
var textIsFocusedTrigger = new DataTrigger
    {
        Binding = new Binding {Source = text1, Path = new PropertyPath("IsFocused")},
        Value = true
    };

textIsFocusedTrigger.Setters.Add(new Setter(Popup.IsOpenProperty, true));

var popupTextIsFocusedTrigger = new DataTrigger
    {
        Binding = new Binding {Source = popupText, Path = new PropertyPath("IsFocused")},
        Value = true
    };

popupTextIsFocusedTrigger.Setters.Add(new Setter(Popup.IsOpenProperty, true));

popupStyle.Triggers.Add(textIsFocusedTrigger);
popupStyle.Triggers.Add(popupTextIsFocusedTrigger);

popup.Style = popupStyle;

我希望这有帮助!

The following code demonstrates having two text boxes in a StackPanel, setting focus to the top text box will open the Popup. At which point, if you then move Focus to the text box contained in the Popup it will remain open. If you move focus to another element, in this instance the second text box in the StackPanel, the Popup will close. As you unable to focus the Popup itself I am actually binding to the IsFocused property of the text box in the Popup.

<StackPanel>
    <TextBox x:Name="text" Text="This is a text box" />
    <TextBox Text="Another Text Box" />
    <Popup PlacementTarget="{Binding ElementName=text}">
        <Popup.Style>
            <Style TargetType="{x:Type Popup}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=text, Path=IsFocused}" Value="True">
                        <Setter Property="IsOpen" Value="True" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding ElementName=popupText, Path=IsFocused}" Value="True">
                        <Setter Property="IsOpen" Value="True" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Popup.Style>
        <TextBox x:Name="popupText" Text="HELLO WORLD" />
    </Popup>
</StackPanel>

To achieve the same thing in C# you don't have to use the ElementName bindings as you already have the elements right at hand. I almost always use XAML to define my elements so I'm sure you could tidy this a bit.

var text1 = new TextBox { Name = "text", Text = "This is a text box" };
var text2 = new TextBox { Text = "Another Text Box" };
var popupText = new TextBox { Name = "popupText", Text = "HELLO WORLD" };
var popup = new Popup { Child = popupText, PlacementTarget = text1 };
var stackPanel = new StackPanel();

stackPanel.Children.Add(text1);
stackPanel.Children.Add(text2);
stackPanel.Children.Add(popup);

var popupStyle = new Style(typeof (Popup));
var textIsFocusedTrigger = new DataTrigger
    {
        Binding = new Binding {Source = text1, Path = new PropertyPath("IsFocused")},
        Value = true
    };

textIsFocusedTrigger.Setters.Add(new Setter(Popup.IsOpenProperty, true));

var popupTextIsFocusedTrigger = new DataTrigger
    {
        Binding = new Binding {Source = popupText, Path = new PropertyPath("IsFocused")},
        Value = true
    };

popupTextIsFocusedTrigger.Setters.Add(new Setter(Popup.IsOpenProperty, true));

popupStyle.Triggers.Add(textIsFocusedTrigger);
popupStyle.Triggers.Add(popupTextIsFocusedTrigger);

popup.Style = popupStyle;

I hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文