wpf: Selecting the Text in TextBox with IsReadOnly

2019-04-19 09:46发布

问题:

I have this TextBox. This TextBox is located in DataTemplate:

<DataTemplate x:Key="myTemplate">
    <TextBox  Text="{Binding Path=FullValue, Mode=TwoWay}" IsEnabled="False"  />
       ...

and I want to allow User to select the whole text inside it (optionally by clicking on the Textbox). And I don't want to use any code behind.

How to do that? Thanks in advance.

回答1:

Using the IsReadOnly property instead of IsEnabled allows the user to select text. Also, if it shouldn't be edited, a OneWay binding should be enough.

The idea of XAML isn't to completely replace code-behind. Most important is that you try to have only UI-specific code in the code-behind, not business logic. That being said, selecting all text is UI-specific and doesn't hurt in the code-behind. Use myTextBox.SelectAll() for that.



回答2:

Removing IsEnabled and setting the TextBox as ReadOnly would allow you to select the text but stop user input.

IsReadOnly="True" 

The only issue with this approach is that although you won't be able to type in the TextBox it will still look 'Enabled'.

To get round that (if you want to?) you can just add a style to lighten the text and darken the background (to make it look disabled).

I've added the following example with a style that will flick the textbox between a disabled and enabled look.

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
    <Style TargetType="{x:Type TextBox}">

        <Style.Triggers>
            <Trigger Property="IsReadOnly" Value="True">
                <Setter Property="Background" Value="LightGray" />
            </Trigger>
            <Trigger Property="IsReadOnly" Value="True">
                <Setter Property="Foreground" Value="DarkGray" />
            </Trigger>
            <Trigger Property="IsReadOnly" Value="False">
                <Setter Property="Background" Value="White" />
            </Trigger>
            <Trigger Property="IsReadOnly" Value="False">
                <Setter Property="Foreground" Value="Black" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid>
    <TextBox Height="23" Margin="25,22,133,0" IsReadOnly="True" Text="monkey"  Name="textBox1" VerticalAlignment="Top" />
    <Button Height="23" Margin="25,51,133,0" Name="button1" VerticalAlignment="Top" Click="button1_Click">Button</Button>
</Grid>

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        textBox1.IsReadOnly = !textBox1.IsReadOnly;
    }


回答3:

One note I just discovered (obviously this is an old question but this might help someone):

If IsHitTestVisible=False then selecting (and therefore Copy) is also disabled.



回答4:

Slightly modified example - to match style of WinForms (not invent your own new style)

By adding <Window.Resources> after <Window> and before <Grid> will make your text box behave like normal winforms textbox.


<Window x:Class="..." Height="330" Width="600" Loaded="Window_Loaded" WindowStartupLocation="CenterOwner">

<Window.Resources>
    <Style TargetType="{x:Type TextBox}">
        <Style.Triggers>
            <Trigger Property="IsReadOnly" Value="True">
                <Setter Property="Background" Value="LightGray" />
            </Trigger>
            <Trigger Property="IsReadOnly" Value="False">
                <Setter Property="Background" Value="White" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Grid>

And of course your textbox must have IsReadOnly="True" attribute set.