Текстовое поле привязки IsFocused для всплывающего окна IsOpen плюс дополнительные условия - PullRequest
3 голосов
/ 18 мая 2009

У меня есть 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 к 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;

1 Ответ

4 голосов
/ 18 мая 2009

Следующий код демонстрирует наличие двух текстовых полей в StackPanel, установка фокуса на верхнее текстовое поле откроет всплывающее окно. В этот момент, если вы затем переместите фокус на текстовое поле, содержащееся во всплывающем окне, оно останется открытым. Если вы переместите фокус на другой элемент, в данном случае второе текстовое поле в 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;

Надеюсь, это поможет!

...