TextBox readonly "on/off" between "double click and lost focus events" in wpf
You can make this with 2 events, MouseDoubleClick and LostFocus
<Grid> <TextBox IsReadOnly="True" MouseDoubleClick="TextBox_MouseDoubleClick" LostFocus="TextBox_LostFocus"/></Grid>
In you procedural code:
private void TextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e){ TextBox textBox = sender as TextBox; textBox.IsReadOnly = false; //textBox.CaretIndex = textBox.Text.Count(); textBox.SelectAll();}private void TextBox_LostFocus(object sender, RoutedEventArgs e){ TextBox textBox = sender as TextBox; textBox.IsReadOnly = true;}
You can use Style and EventTrigger to do that
<Window xmlns:sys="clr-namespace:System;assembly=mscorlib" ...> <Window.Resource> <Style x:Key="MyTextBoxStyle" TargetType="{x:Type TextBox}"> <Style.Triggers> <EventTrigger RoutedEvent="LostFocus"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="(TextBox.IsReadOnly)"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <sys:Boolean>True</sys:Boolean> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> <EventTrigger RoutedEvent="MouseDoubleClick"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="(TextBox.IsReadOnly)"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <sys:Boolean>False</sys:Boolean> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Style.Triggers> </Style> </Window.Resource> ... <TextBox Style="{StaticResource MyTextBoxStyle}" .../></Window>
You can use System.Windows.Interactivity
assembly (msdn) to do that.
First: create helper class to set properties:
public class SetterAction : TriggerAction<DependencyObject>{ public SetterAction() { Setters = new List<Setter>(); } public List<Setter> Setters { get; set; } protected override void Invoke(object parameter) { foreach (var item in Setters) { AssociatedObject.SetValue(item.Property, item.Value); } }}
XAML:
<TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="Transparent" IsReadOnly="True" BorderThickness="0" TextWrapping="Wrap" Height="30" Width="200"> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseDoubleClick"> <i:EventTrigger.Actions> <local:SetterAction> <local:SetterAction.Setters> <Setter Property="TextBox.IsReadOnly" Value="False" /> <Setter Property="TextBox.Background" Value="Green" /> </local:SetterAction.Setters> </local:SetterAction> </i:EventTrigger.Actions> </i:EventTrigger> <i:EventTrigger EventName="LostFocus"> <i:EventTrigger.Actions> <local:SetterAction> <local:SetterAction.Setters> <Setter Property="TextBox.IsReadOnly" Value="True" /> <Setter Property="TextBox.Background" Value="Red" /> </local:SetterAction.Setters> </local:SetterAction> </i:EventTrigger.Actions> </i:EventTrigger> </i:Interaction.Triggers></TextBox>
Where i
is:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"