I'm trying to disable double clicks on buttons and currently the only way I know is to handle the PreviewMouseDoubleClick and set the e.Handled = true.
Is there a way to do this in a button style? Or even better, disable double clicks application wide?
I would use an attached behavior (see this article). For example, say I create an attached behavior called DisableDoubleClickAttachedBehavior which handles the double click mouse event and sets e.Handled = true.
Then, you can nicely set the property via a style in XAML:
<Style x:Key="DisableDoubleClickStyle">
<Setter Property="p:DisableDoubleClickAttachedBehavior.Enabled" Value="True" />
</Style>
<Button Style="{StaticResource DoubleClickDisabledStyle}">Hi!</Button>
Or, you can override the style for all buttons (like you wanted):
<Style TargetType="Button">
<Setter Property="p:DisableDoubleClickAttachedBehavior.Enabled" Value="True" />
</Style>
I tested this and it seems to work nicely.
I don't think it can be done in a style or application-wide. Best bet might be a class derived from Button that includes that event handler by default.
Related
There's a custom touchscreen keyboard in my app built according to this: https://www.codeproject.com/Articles/32568/A-Touch-Screen-Keyboard-Control-in-WPF.
I also have a ResourceDictionary containing all styles and templates. In the TextBox style, I can set the keyboard ON/OFF:
<Style TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="14" />
<Setter Property="Padding" Value="4" />
<Setter Property="k:TouchScreenKeyboard.TouchScreenKeyboard" Value="True"/>
</Style>
I would like the user to be able to turn it on or off from the UI, but can't figure out how to reach this property from code behind. I would like to make it without naming the style, since it's pretty commonly used throughout the app.
I tried this, but (no surprise) get ArgumentNotFoundException:
Style s = Application.Current.FindResource("defTextBox") as Style;
s.RegisterName("Keyboard.TouchScreenKeyboard.TouchScreenKeyBoard",false);
Any help would be appreciated!
You shoud be able to set the TouchScreenKeyboard attached property for an individual TextBox like this:
TouchScreenKeyboard.SetTouchScreenKeyboard(textBox1, false);
Changing the defintion of the implicit Style itself after it has already been applied to all TextBox elements doesn't make much sense though. You should define the default value in XAML and then change the value for individual TextBoxes dynamically at runtime if you need to.
I need behavior like in the excel Find and Replace dialogBox that's why i asked like this. In this image you can able to see FindNext is always focused
I could able to set the focus to single element that is either Textbox or Button. But my requirement is always i need to set focus to Button even i click the some other controls within the window.
As I said in the comment, just set IsDefault="True" for your button will give you the result you want in the images you posted.
e.g.
<Button Content="Button" IsDefault="True" />
Result:
You can see the button will be highlighted even when user input into the textbox.
Not sure why you want to do this. But you can always set up a PreviewMouseLeftButtonDown on the Window, and check the e.OriginalSource property to see if it is a Control you want to give focus to. If it is not something you want to give focus to, simply set e.Handled to true.
But, seriously, it is still weird why you want to do this.
Edited because of your edited question
The "Find Next" button only visually looks focused. The focus is still given to the search TextBox or the replace TextBox. When you hit "Enter", the TextBox handles that KeyEvent, and executes the same Command as the "Find Next" button.
If you want to do something like that, you probably can consider this:
Add a property (probably bool ShouldButtonLookFocused) somewhere
Set up a Data Trigger in the button that binds to this ShouldButtonLookFocused property), set trigger value to true (e.g. <DataTrigger Binding="{Binding Path=ShouldButtonLookFocused}" Value="True">
Set the data trigger's setter to whatever visual changes you want to indicate this.
Then add bindings to which ever other TextBox controls, which when focused, you would want the button to "look focused". The binding should be to this ShouldButtonLookFocused property, and most likely you need to use a Converter for this.
Example:
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShouldButtonLookFocused}" Value="True">
<!-- Whatever visual thing you can think of -->
<Setter Property="Border" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
public static readonly DependencyProperty ShouldButtonLookFocusedProperty =
DependencyProperty.Register("ShouldButtonLookFocused",
typeof(bool),
typeof(WhicheverClassThisIsIn));
public bool ShouldButtonLookFocused
{
get
{
return (bool)GetValue(ShouldButtonLookFocusedProperty);
}
set
{
SetValue(ShouldButtonLookFocusedProperty, value);
}
}
<TextBox Name="SearchBox"
IsFocused="{Binding Path=ShouldButtonLookFocused,
Converter={StaticResource MyConverter}"
/>
I did not test this though, maybe you can try it and tell me how it goes.
I created a WPF (.Net 4) UserControl containing some ComboBoxes and a TextBox. In XAML, some ValidationRules are bound to the TextBox. If the TextBox contains invalid data, a red frame is shown, and the tooltip is set to the error description. Works well.
Next, I placed two instances of that UserControl on a form, and added a button. In XAML, the button is connected to a RelayCommand of the ViewModel. Now I want the button to be enabled only when both of the UserControls contain valid data only.
Not a problem, I thought, let me use a strategy which works elsewhere. I added a trigger:
<Button Content="_OK" ... Command="{Binding Path=OKCommand}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="false" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=cascadingComboFrom, Path=(Validation.HasError)}" Value="false" />
<Condition Binding="{Binding ElementName=cascadingComboTo, Path=(Validation.HasError)}" Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="true" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
But there is a catch: Validation.HasError is always false for the UserControls - the Validation failed for an element inside the UserControl, not for the UserControl proper.
I know that I can register the Click event of the button, check the validity there using the method shown in Detecting WPF Validation Errors, and prevent the execution of the RelayCommand by setting the Handled property of the RoutedEventArgs to true. But that looks more like WTF than WPF.
What do you suggest? How can I retrieve the Validation Errors of the UserControl's children? Or how can I get them in the RelayCommand's CanExecute method? Or some other tricks?
You can set a property on the command binding called ValidatesOnDataErrors.
Implementation would look something like this:
<Button Content="_OK" Command="{Binding, Path=OKCommand, ValidatesOnDataErrors=True}"/>
You can read more about it here.
The Button.IsEnabled property is already hard wired to the CanExecute method of your RelayCommand, so all you need to do is to set that return value to false when the form fields are invalid:
private bool CanExecute(object commandParameter)
{
return areFormFieldsValid;
}
Now, how you set the bool areFormFieldsValid variable to true or false is up to you... there are several ways of doing that. Personally, I prefer to use the IDataErrorInfo interface, which has a handy Error property that you can check. There are many online tutorial on how to implement this, so I won't repeat that here... however, the end result is something like this:
private bool CanExecute(object commandParameter)
{
return string.IsNullOrEmpty(yourDataObject.Error);
}
A lot of programs display a little sentence of information in a label in a status bar when you hover over an control to tell you what it will do if you click it and then it resets the text when the mouse leaves its area. One example is PaintShop Pro X4.
I want to do this in my application. I could of course easily do it by changing the content of the label in a status bar using the mouse enter event and then empty it on the mouse leave event like I have done in some of my previous programs but that means I have to create those 2 event handlers for every control that I want to have display its information in the status bar (I could use one handler for the reset and have all controls use it though) but I have a very large number of controls for this. Is there a better way I could do this without using any C# or event handlers? Could I do it in XAML, sort of like the boolean to visibility converter but one that just sets text to something because I do not really want to create loads of event handlers for controls that I may not even use for anything (like group boxes, I will naver use them in code but I want a status information for it)? Thank you.
You can use the UIElement.IsMouseOver property in a Trigger to do what you want. Try something like this:
<TextBlock>
<TextBlock.Style>
<Style>
<Setter Property="Text" Value="Normal text" />
<Style.Triggers>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<Setter Property="Text" Value="Mouse over text" />
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
I am creating a simple custom control extending from toggle button that allows the user to specify checked and unchecked content directly in XAML. It works well but it is based on a trigger, and I don't know how to define the trigger except in a style. If I define the style, then I lose anything set outside of the custom control.
What I would like to be able to do is just append this trigger to any existing style set elsewhere on the control.
Here's the XAML for the style/trigger.
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Content" Value="{Binding RelativeSource={RelativeSource Self}, Path=UncheckedContent}" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content"
Value="{Binding RelativeSource={RelativeSource Self}, Path=CheckedContent}" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
I tried inheriting the style via the BasedOn with a default type but it won't work if the custom control has an explicit style set by its parent. I also considered EventTriggers but I do not believe there would be an event to initialize the control.
Thanks for any help anyone can offer. :)
Just to clear things up on the terminology here: A user control is a control that derives from the UserControl class. If I understood you right you derived from ToggleButton to add the UncheckedContent and CheckedContent properties. In that case you have created a custom control. It's always easier to follow if we agree on common terminology :)
As far as I know you can not do such a generic style inheritance in XAML. You always have to specify explicitly what style a another style is based upon. Your style can either be based on the default style for ToggleButton or on a specific other style. If you can't build a style inheritance chain that respects that, this approach won't work.
But since you have a custom control, couldn't you write a default style for it that is based on the default toggle button style like this?
<Style TargetType="{x:Type CustomToggleButton}"
BasedOn="{StaticResource {x:Type ToggleButton}}">
Then whenever you apply an explicit style to a toggle button you would specify that it is based on the default toggle button style.
Also you could write a (default) control template for your new toggle button in Themes\Generic.xaml that contains the above triggers. In blend you can get a copy of the default template for toggle button ("Edit Template"->"Edit a Copy") so you can make sure that your toggle button looks exactly like the normal toggle button. Then incorporate the triggers above into that template.
BTW: you do not have to create a new control just to add new properties. You can add new properties to an existing control using attached properties. They can be used from XAML just like normal properties.