Enable a disabled textbox in wpf - wpf

Is it possible to have a TextBox that is disabled by default, but becomes enabled when a user double-clicks it?

you can place your TextBox inside StackPanel like this:
<StackPanel MouseLeftButtonDown="StackPanel_MouseDown">
<TextBox Name="textBox1"/>
</StackPanel>
Then in StackPanel event handler:
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount >= 2)
{
textBox1.IsEnabled = true; //only hit here on DoubleClick
}
}
you can also simulate StackPanel DoubleClick as described on this question:
WPF StackPanel with Click AND DoubleClick

That's very unusual, also when a control is disabled it is not expected to get input. Users seeing a disabled control normally would not even try to click/double click on it.
Maybe you can add a check box to enable it (or the function belonging to it), or show a message box when double clicking it when it is not allowed/meant to. In this case you also can clearly add a reason why it cannot be double clicked.
What I have seen before is a checkbox without text right before the control. When you click the checkbox it enables the control (text box in your case) after it. You can even use a tooltip for the check box to provide help information what the checkbox is doing.

I would try attaching to the PreviewMouseDown event and enable/disable there.
Otherwise you will have to do the old VB6 trick of having a transparent control above the textbox to receive the click event.

This question is old, but maybe I can help someone that finds a solution for this.
In a recent project I've needed to simulate two states: view and edit. I've do this using a textbox. In view state, value is displayed but you cannot got focus clicking on the control. To enable editing mode you need to double click the control. To avoid the control getting focus by clicking on it and also the disadvantages of disable it, I've used two preview events for control the behaviour of the textbox and adapt it's responses to application needs and state. One of the events is PreviewMouseDown:
private void tbxVariable_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if(!tbxVariable.IsFocused && e.ChangedButton == MouseButton.Left)
e.Handled = true;
}
In this event we will block the mouse down button if our textbox isn't focused yet. This prevents textbox to get focus. So it will behave like a label. When the control is focused, this event isn't blocked and is propagated towards the control. Note that maybe you need to change the cursor because editing cursor is used when the mouse is over the control. Note also, that we are blocking only the left button.
The second event looks like:
private void tbxVariable_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && !tbxVariable.IsFocused)
tbxVariable.Focus();
}
In the second event we will bring the focus to the control on double left click if it isn't focused yet. If control has focus so we will let the event propagate and the control will behave normally.
In my case I've created a special style for the textbox leaving borders, backgrounds, and all style behaviours. This is the XAML code:
<Style x:Key="InlineEditorTextBox" TargetType="{x:Type TextBox}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="MinWidth" Value="5" />
<Setter Property="MaxHeight" Value="16" />
<Setter Property="AllowDrop" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<ScrollViewer Margin="0" x:Name="PART_ContentHost" VerticalScrollBarVisibility="Disabled" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

keep tooltip opened if a property is set to true until user clicks anywhere with the mouse

I have an WPF tooltip defined within a dictionary.xaml that I want to apply to all my items, labels, buttons, etc. I import this dictionary in my view.
<Style x:Key="{x:Type ToolTip}" TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="HorizontalOffset" Value="1" />
<Setter Property="VerticalOffset" Value="1" />
<Setter Property="Background" Value="White" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontSize" Value="12" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="DataContext" Value="{Binding Path=PlacementTarget.DataContext, RelativeSource={x:Static RelativeSource.Self}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Canvas Width="225" Height="131">
<Path x:Name="Container"
Canvas.Left="0"
Canvas.Top="0"
Margin="0"
Data="M8,7.41 L15.415,0 L22.83,7.41 L224,7.41 L224,130 L0,130 L0,7.41 L8,7.41"
Fill="{TemplateBinding Background}"
Stroke="Gray">
<Path.Effect>
<DropShadowEffect BlurRadius="10"
Opacity="0.5"
ShadowDepth="4" />
</Path.Effect>
</Path>
<TextBlock Canvas.Left="10"
Canvas.Top="10"
Width="100"
Height="65"
Text="{TemplateBinding Content}"
TextWrapping="WrapWithOverflow" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
so I can use it as below:
<Label x:Name="myLabel"
ToolTip="This is a custom tooltip for my label."
ToolTipClosing="tt_ToolTipClosing"/>
also I have other items:
<Button x:Name="myBtn"
Tooltip="This is a custom tooltip for my button"
ToolTipClosing="tt_ToolTipClosing"/>
Tooltip is working fine, when I hover the mouse on it, the tooltip is shown.
Now I am trying to do below 2 things:
Implement a tooltip closing event handler that works for all my items (labels, buttons, etc.)
Keep the tooltip always opened until user clicks on anywhere in the screen with the mouse if a property keepOpened is set to true. Otherwise, if keepOpened is set to false, it behaves as a normal tooltip, it closes automatically when mouse leaves item.
In the code behind now I have below event handler (I have got this code from here):
private void tt_ToolTipClosing(object sender, ToolTipEventArgs e)
{
if (keepOpened)
{
// TODO: Determine who is the sender, a label, a button, etc.
// We suppose in this example it is a label
Label myLabel = sender as Label;
ToolTip tt = myLabel.ToolTip as ToolTip;
if (tt.PlacementTarget == null)
{
tt.PlacementTarget = myLabel;
}
tt.IsOpen = true;
}
}
For first point, I guess I need to use a switch to determine if sender is a button, label, etc. and then get the tooltip by casting it. I do not know if there are any other better way to do it. If so, please tell me.
For second point, KeepOpened would be a property defined in the view model, so I guess I need to use a command instead and move the above event to the view model, right? I know that I can use a popup instead but i don't want to use it as it is always on top of all desktop objects - even if you switch to another program, the popup will be visible and obscure part of the other program.
Also, now I have a problem in above event handler when casting to a Tooltip, tt is getting null. Why? I have set the datacontext in the style that is defined in the dictionary.xaml.
If you want to apply this style as a generic style for multiple controls, you should remove the x:Key part which should be just a string anyway. Change this:
<Style x:Key="{x:Type ToolTip}" TargetType="ToolTip">
to:
<Style TargetType="{x:Type ToolTip}">
Also, I would get rid of that Canvas with fixed size. Use a Border and put a Grid inside of it where you put the Path and the TextBlock. Leave the tooltip size itself to the content. This Canvas Width="225" Height="131" doesn't look nice.
For point 2, to make the tooltip to not close automatically after 5 seconds, but only when the user moves the mouse pointer away from the control, you can add this in your code:
ToolTipService.ShowDurationProperty.OverrideMetadata(typeof(DependencyObject), new FrameworkPropertyMetadata(Int32.MaxValue));
Make sure you call this code only once, for example in App.xaml.cs.
Now your tooltips should stay open several weeks if the user keeps the mouse pointer over the control that displays the tooltip, allowing the user to read the content of it.
I guess I need to use a switch to determine if sender is a button, label, etc. and then get the tooltip by casting it. I do not know if there are any other better way to do it. If so, please tell me.
You could cast the sender argument to a FrameworkElement and then access the ToolTip property:
private void tt_ToolTipClosing(object sender, ToolTipEventArgs e)
{
FrameworkElement fe = (FrameworkElement)sender;
switch (fe.ToolTip)
{
case string s:
//do something with the string s
break;
case ToolTip tt:
//do something with the ToolTip tt
break;
}
}

WPF: Remove dotted border around focused ListView

When my application change state to normal i want to set focus over my ListView:
private void Window_StateChanged(object sender, EventArgs e)
{
if (WindowState == WindowState.Normal)
ListViewUsers.Focus();
}
I am doind that in order to use Up & Down arrows Keys to navigate my ListViewItem instead of click on my ListView first to set focus.
So this works fine except the fact that i have this dotted border around my ListView.
I try to add this line to my ListViewItem Style:
<Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListViewItem}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/> ....
But unfortunately i still see this dotted border.
Any seggestions ?
It works fine for me.
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
How you apply style? Are you sure that ListView items use this style?

How to change all TextBox's Foreground Color in an application

In my app (C# WPF) I have about 30 or 40 textBoxes in more grids and I want to change their foreground color in a loop. I use the code below and it works. But I want to use it for the whole project, not only for concrete grid
xaml code
<grid x:Name"stk">
.... some textBoxes ...
</grid>
*.cs code
foreach (TextBox item in this.stk.Children.OfType<TextBox>())
{
if (item.Name.StartsWith("txt"))
item.Foreground = Brushes.Orange;
}
So, when I have more grids, I have to put x:Name="..." into each one and this implies more foreach loops.
Much Simpler Way
Define a Style with TargetType set to Textbox and with no Key. This way this style will be applied to all textbox in the application without the need to bind the style or the foreground for each textbox.
<Application.Resources>
<SolidColorBrush Color="Red" x:Key="txtColor" />
<Style TargetType="TextBox">
<Setter Property="Foreground" Value="{DynamicResource txtColor}" />
</Style>
</Application.Resources>
To change the Foreground Color.
private void Button_Click(object sender, RoutedEventArgs e)
{
if (Application.Current.Resources.Contains("txtColor"))
{
Application.Current.Resources["txtColor"] = new SolidColorBrush(Colors.Blue);
}
}
Bind all your Textbox's Foreground to a common Brush Resource. Define the brush resource common to Project and access it everywhere.
In App.XML declare the brush resource so that you can access it anywhere from your project. [Note : You can also define it resource Dictionary and refer it]
<Application.Resources>
<SolidColorBrush Color="Red" x:Key="txtColor" />
</Application.Resources>
In All your textbox bind the foreground to the "txtColor" brush resource.
<TextBox Foreground="{DynamicResource txtColor}" Text="TextBox" />
To change the Foreground color of all textbox's, then change the commonly defined resource's color. Below I changed the color in button click. Access th resource using the key and set the new brush which you want to set.
private void Button_Click(object sender, RoutedEventArgs e)
{
if (Application.Current.Resources.Contains("txtColor"))
{
Application.Current.Resources["txtColor"] = new SolidColorBrush(Colors.Blue);
}
}
Ignore my code and have a look at this answer
Find all controls in WPF Window by type
So ... To solve my problem where I couldn't change foreground color of textBoxes when some textBox is disabled ... I used code below ...
<Application.Resources>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Orange"/>
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>
What about creating a "usercontrol" based on the standard textbox where you control the appearance of the foreground. This way you have a reusable control that you can use anywhere you want and have "full control" over it's appearance and behaviour. Take a look at this article, or this one for some examples that might help you go the right way ;)

WP7 Disabled Button Style

I am trying to do change the color of a disabled button's border/text.
Code:
<Style x:Key="TopTabChooserButtonDisabled" TargetType="Button">
<Setter Property="Foreground" Value="Orange" />
</Style>
But it doesn't affect the button at all in Silverlight. Does anybody know what will make it change? THanks.
You can do this fairly easily by retemplating the control in blend.
Rclick the control, edit template, edit a copy. You then have access to all the states and constituent objects that make up the control in each of those states to change properties of each as needed.

WPF Usercontrol with textboxes

I have a WPF user control with a number of textboxes, this is hosted on a WPF window.
The textboxes are not currently bound but I cannot type into any of them.
I have put a breakpoint in the KeyDown event of one of the textboxes and it hits it fine and I can see the key I pressed.
The textboxes are declared as
<TextBox Grid.Row="3"
Grid.Column="4"
x:Name="PostcodeSearch"
Style="{StaticResource SearchTextBox}"
KeyDown="PostcodeSearch_KeyDown"/>
The style is implemented as
<Style x:Key="SearchTextBox"
TargetType="{x:Type TextBox}">
<Setter Property="Control.Margin" Value="2"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Width" Value="140"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
I am hoping I have overlooked something obvious.
EDIT: I only added the KeyDown and KeyUp events just to prove that the keys presses were getting through. I do not have any custom functionality.
If your PostcodeSearch_KeyDown-method (or anybody else before the textbox in the event-chain, could also be some parent-control in the Preview_KeyDown-Event) sets e.Handled = true (e being the eventArgs), the event will not be propagated to further consumers (as the textbox) and thus no action will occur.
Another reason might be that your WPF-Window is hosted in a WinForms-Application, then you will need to call
ElementHost.EnableModelessKeyboardInterop(YourWindow);
To make keyboard interaction work (google/bing for WPF WinForms InterOp for a full explanation)

Resources