3

我有一个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.IsOpenTextBox.IsFocused

2.)绑定TextBox.IsFocusedPopup.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;
4

1 回答 1

4

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

我希望这有帮助!

于 2009-05-18T19:19:32.603 回答