0
votes

I have a textbox which I am trying to abide by the following rules:

Textbox must always be visible when it has focus

Textbox must always hide when it doesnt have focus AND it is empty

I have a dependency property setup which allows me to refocus the textbox, so that it shows. This works "one-way" in that I can focus a textbox that is collapsed and it shows. But once I move the focus out of the textbox (and its empty) it always remains.

How can I collapse the textbox, once focus is lost AND it is empty? (Note: I also want to SHOW the box, if text is entered (it is bound to other text boxes, which may have text entered, this is bound two-way).

<Style x:Key="textBoxHider" TargetType="{x:Type TextBox}" BasedOn="{StaticResource storyForgeTextBox}">
    <Style.Triggers>
        <Trigger Property ="IsMouseOver" Value="True">
            <Setter Property= "BorderBrush" Value="LightCyan"/>
            <Setter Property= "BorderThickness" Value="2"/>
        </Trigger>
        <Trigger Property="IsFocused" Value="True">
            <Setter Property= "BorderBrush" Value="LightSkyBlue"/>
            <Setter Property= "BorderThickness" Value="2"/>
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="Text" Value=""></Condition>
                <Condition Property="IsFocused" Value="False"></Condition>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
                <Setter Property="Visibility" Value="Collapsed"></Setter>
            </MultiTrigger.Setters>
        </MultiTrigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsFocused" Value="True"></Condition>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
                <Setter Property="Visibility" Value="Visible"></Setter>
            </MultiTrigger.Setters>
        </MultiTrigger>
    </Style.Triggers>
</Style>

Edit: for clarity I have simplified it even further and its still not collapsing. Checking the value in Snoop. IsFocused is correctly being set to FALSE and TRUE when I am not focused/focused.

<Style x:Key="TextBoxHider" TargetType="{x:Type TextBox}" BasedOn="{StaticResource storyForgeTextBox}">
    <Style.Triggers>
        <Trigger Property ="IsMouseOver" Value="True">
            <Setter Property= "BorderBrush" Value="LightCyan"/>
            <Setter Property= "BorderThickness" Value="2"/>
        </Trigger>
        <Trigger Property="IsFocused" Value="True">
            <Setter Property= "BorderBrush" Value="LightSkyBlue"/>
            <Setter Property= "BorderThickness" Value="2"/>
            <Setter Property="Visibility" Value="Visible"></Setter>
        </Trigger>
        <Trigger Property="IsFocused" Value="False">
            <Setter Property="Visibility" Value="Collapsed"></Setter>
        </Trigger>
    </Style.Triggers>
</Style>

edit:edit: I am now stumped. The border brush is being set to RED no problem. So the IsFocused is being fired, but its not collapsing the box?

<Style x:Key="storyForgeTextBoxHider" TargetType="{x:Type TextBox}" BasedOn="{StaticResource storyForgeTextBox}">
    <Style.Triggers>
        <Trigger Property ="IsMouseOver" Value="True">
            <Setter Property= "BorderBrush" Value="LightCyan"/>
            <Setter Property= "BorderThickness" Value="2"/>
        </Trigger>
        <Trigger Property="IsFocused" Value="True">
            <Setter Property= "BorderBrush" Value="LightSkyBlue"/>
            <Setter Property= "BorderThickness" Value="2"/>
            <Setter Property="Visibility" Value="Visible"></Setter>
        </Trigger>
        <Trigger Property="IsFocused" Value="False">
            <Setter Property="Visibility" Value="Collapsed"></Setter>
            <Setter Property="BorderBrush" Value="Red"></Setter>
        </Trigger>
    </Style.Triggers>
</Style>
3
Try with the "Opacity" propertyDinesh Kumar P
@Kumar - this will make it invisible. Not collapsed.Asheh
I have edited my answer, just check it out.Dinesh Kumar P

3 Answers

1
votes

Please check this code; I have made use of Height and Visibility property; Add the code run the application and try the suggestions based on your questions,

Operation 1: Textbox must always be visible when it has focus

Just play with 'Tab' key. When ever second textbox gets focus, it will be visible. When it loses focus, it will be collapsed. (I have used "Height" property)

Operation 2: Textbox must always hide when it doesnt have focus AND it is empty

Just delete the text in 1 textbox out of 2 available textbox. When its empty , second textbox will get collapsed. (I have used "Visibility" property)

XAML code:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sampleApp="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <sampleApp:TextToVisibilityConverter x:Key="TextToVisibilityConverter"/>
</Window.Resources>
<Grid ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBox x:Name="textBox1" Grid.Row="0" Text="{Binding Text,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" BorderThickness="5" Height="50" Width="300"/>
    <TextBox x:Name="textBox2" Grid.Row="1" Text="{Binding Text,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="300" Visibility="{Binding Text,Converter={StaticResource TextToVisibilityConverter}}"
             BorderThickness="5">
        <TextBox.Style>
            <Style TargetType="TextBox">
                <Style.Triggers>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter Property="Height" Value="50"/>
                    </Trigger>
                    <Trigger Property="IsFocused" Value="False">
                        <Setter Property="Height" Value="0"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </TextBox.Style>
    </TextBox>
    <Button Grid.Row="2" VerticalAlignment="Center" Content="Just a Button"/>
</Grid>

C# Code:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private string m_Text = "Hello!!";

    public string Text
    {
        get { return m_Text; }
        set { m_Text = value; OnPropertyChanged("Text"); }
    }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
}

public class TextToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            var text = value.ToString();
            if (string.IsNullOrEmpty(text))
            {
                return Visibility.Collapsed;
            }
            else
            {
                return Visibility.Visible;
            }
        }
        else
        {
            return Visibility.Collapsed;
        }

    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
0
votes

I'm guessing you've got something along these lines in your XAML:

<TextBox Style="{StaticResource textBoxHider}" Visibility="Collapsed">
    ...
</TextBox>

The visibility won't be set by the trigger because it is set directly (inline in this case), and style setters by design do not affect properties which are set directly (inline, as XAML tag, in code-behind). In order to make it work you should set initial visibility value via style, for example:

<TextBox>
    <TextBox.Style>
        <Style TargetType="TextBox" BasedOn="{StaticResource textBoxHider}">
            <Setter Property="Visibility" Value="Collapsed"/>
        </Style>
    </TextBox.Style>
    ...
</TextBox>
0
votes

After you have set textBox.Visibility = Visibility.Visible via code, any triggers setting visibilty will have no effect.

Please see MSDN's Dependency Property Value Precedence for more information on that, in particular :

Be cautious of setting values for properties that have theme-level trigger behaviors and make sure you are not unduly interfering with the intended user experience for that control.