Okay. I am trying on and off mouse events on the click of the toggle button in wpf. so far this is what i have..
the xaml is as follows
<telerik:RadToggleButton Name="Percentage" Height="25" Width="25" Style="{StaticResource SelectionGridStyle}" Checked="Percentage_Click"
HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<telerik:RadToggleButton.ToolTip>
<ToolTip Content="{localization:Translate Percentage}"></ToolTip>
</telerik:RadToggleButton.ToolTip>
</telerik:RadToggleButton>
the this is the code behind.
private void Percentage_Click(object sender, RoutedEventArgs e)
{
RadToggleButton btn = sender as RadToggleButton;
btn.IsChecked = true;
//if (e.Handled == true)
// e.Handled = false;
//else if(e.Handled == false)
// e.Handled = true;
}
i want to handle the drag of a mouse for selection purpose when on else off. is there i way to achieve this?? Thank you.
Related
I am able to dynamically add images into the WPF Canvas control as child elements but failing to drag & drop those images inside the canvas. Please help me as how could i move or drag/drop images inside the canvas window.
Thanks in advance.
Below is what I have done so far:
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0" Width="430"
HorizontalAlignment="Left" VerticalAlignment="Top" AllowDrop="True"
PreviewMouseLeftButtonDown="MouseLeftButtonDown"
PreviewMouseLeftButtonUp="MouseLeftButtonUp"
PreviewMouseMove="MouseMove"
MaxWidth="430" MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
</Grid>
**Code**
OpenFileDialog op = new OpenFileDialog();
op.Title = "Select Multiple Pictures";
op.Multiselect = true;
op.Filter = "Image files (*.jpg, *.jpeg, *.jpe, *.jfif, *.png) |
*.jpg; *.jpeg; *.jpe; *.jfif; *.png";
foreach (string imageFile in op.FileNames)
{
Image img = new Image();
img.Source = new BitmapImage(new Uri(imageFile));
img.Height = 100;
img.Width = 100;
img.AllowDrop = true;
Canvas.SetTop(img, y); //Setting up images to the Top position
Canvas.SetLeft(img, x); //Setting up images to the left position
canvasImages.Children.Add(img);
}
private new void MouseLeftButtonDown(object sender,
MouseButtonEventArgs
e)
{
IsDragging = true;
draggedItem = (UIElement)sender;
itemRelativePosition = e.GetPosition(draggedItem);
}
private new void MouseMove(object sender,
System.Windows.Input.MouseEventArgs e)
{
if (!IsDragging)
return;
Point canvasRelativePosition = e.GetPosition(canvasImages);
Canvas.SetTop(draggedItem, canvasRelativePosition.Y -
itemRelativePosition.Y);
Canvas.SetLeft(draggedItem, canvasRelativePosition.X -
itemRelativePosition.X);
}
private new void MouseLeftButtonUp(object sender, MouseButtonEventArgs
e)
{
if (!IsDragging)
return;
IsDragging = false;
}
Ok, a few things wrong here...
1) Your mouse down handler has to be on the image, not the canvas, otherwise your code has no way of knowing which item is being dragged.
2) Once you've clicked on an image the handler should capture the mouse for the canvas so that you get all mouse move messages.
3) The Canvas MouseMove and MouseUp handlers then need to be handled accordingly.
4) The Canvas needs to have a background. If you don't give it a background then it's effectively transparent to the hit-testing and you won't get mouse messages for it. If you don't want it to have a visible background then set it to Transparent.
So your Canvas tag needs to look like this:
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0" Width="430"
HorizontalAlignment="Left" VerticalAlignment="Top" AllowDrop="True"
PreviewMouseLeftButtonUp="CanvasImages_PreviewMouseLeftButtonUp"
PreviewMouseMove="CanvasImages_PreviewMouseMove"
MaxWidth="430" MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
Background="Transparent" />
And every image you create needs to have a handler set for it's MouseDown event:
img.MouseLeftButtonDown += Img_MouseLeftButtonDown;
Then it's just a matter is implementing your handlers like this:
private void Img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.draggedItem = (UIElement)sender;
itemRelativePosition = e.GetPosition(this.draggedItem);
e.Handled = true;
}
private void CanvasImages_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (this.draggedItem == null)
return;
var newPos = e.GetPosition(canvasImages) - itemRelativePosition;
Canvas.SetTop(this.draggedItem, newPos.Y);
Canvas.SetLeft(this.draggedItem, newPos.X);
canvasImages.CaptureMouse();
e.Handled = true;
}
private void CanvasImages_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (this.draggedItem != null)
{
this.draggedItem = null;
canvasImages.ReleaseMouseCapture();
e.Handled = true;
}
}
#Mark, Here are the XAML code and the respective Class for your perusal. Basically I am allowing multiple selection of images by "OpenFileDialog()" and adding those images dynamically to Canvas control as mentioned in my previous code, which then i am failing to drag around those images internally within the Canvas control.
Below is the XAML Code
<Window x:Class="PicturesMovement.CanvasControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Connectlite Clients"
Height="394" Width="445"
WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
<Grid Margin="0,0,2,0" Background="{DynamicResource {x:Static
SystemColors.MenuBarBrushKey}}">
<Button x:Name="Select" Content="Select" HorizontalAlignment="Left"
Height="22" Margin="329,328,0,0" VerticalAlignment="Top" Width="42"
Click="SelectImages"/>
<Button x:Name="Cancel" Content="Cancel" HorizontalAlignment="Left"
Margin="374,328,0,0" VerticalAlignment="Top" Width="49"
Click="closeBox"/>
<Canvas x:Name="canvasImages" Height="325" Margin="0,0,0,0"
Width="430" HorizontalAlignment="Left" VerticalAlignment="Top"
AllowDrop="True" PreviewMouseDown="PreviewMouseDown"
PreviewMouseUp="PreviewMouseUp"
PreviewMouseMove="PreviewMouseMove" MaxWidth="430"
MaxHeight="325"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
</Grid>
</Window>
Below are the respective Class that triggers those Mouse Events
public partial class CanvasControl : System.Windows.Window,
System.Windows.Markup.IComponentConnector {
this.canvasImages.PreviewMouseDown += new
System.Windows.Input.MouseButtonEventHandler
(this.PreviewMouseDown);
this.canvasImages.PreviewMouseUp += new
System.Windows.Input.MouseButtonEventHandler
(this.PreviewMouseUp);
this.canvasImages.PreviewMouseMove += new
System.Windows.Input.MouseEventHandler
(this.PreviewMouseMove);
}
Any suggestions will be highly appreciated...Thanks
I have a simple dialog with a SpinEdit and two buttons: OK_Button and Cancel_Button. I've set a mask for the value in the SpinEdit and the dialog won't let me press the cancel button when the value is invalid. I've tried changing the SpinEdit's property to InvalidValueBehavior="AllowLeaveEditor" but then I can click both, OK and cancel button. Is there a way to ONLY allow pressing cancel when the value is incorrect?
XAML:
<dxe:SpinEdit x:Name="dxSpinEdit"
Height="23" MinWidth="200" Width="Auto"
HorizontalAlignment="Right"
Text="{Binding Value, Mode=TwoWay}"
MaskType="Numeric"
IsFloatValue="{Binding FloatValue}"
MinValue="{Binding MinValue}"
MaxValue="{Binding MaxValue}"
Mask="{Binding Mask, Mode=OneWay}"
MaxLength="{Binding Path=InputLength}"
MaskShowPlaceHolders="{Binding ShowPlaceHolder}"
InvalidValueBehavior="WaitForValidValue"
/>
<StackPanel Grid.Row="1" x:Uid="OKCancel_Buttons" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<Button Height="23" x:Name="OK_Button" Click="OK_Click" Content="OK" IsDefault="True" HorizontalAlignment="Right" MinWidth="95" />
<Button Height="23" x:Name="Cancel_Button" Click="Cancel_Click" Content="Cancel" HorizontalAlignment="Right" MinWidth="95" PreviewMouseDown="win_PreviewMouseDown" />
</StackPanel>
I looked up this issue on the devexpress forum but their solution didn't work for me. I've implemented the MouseDownPreview event like so:
C# (code behind)
private void OK_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
private void win_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if(e.Source == Cancel_Button)
{
DialogResult = false;
Close();
}
}
But the event wasn't handled at all. I'd like to keep the property InvalidValueBehavior at the value "WaitForValidValue" but at the same time I'd like to allow pressing the Cancel button.
Even if you're not going to go the full MVVM route, you should switch from using click events to an ICommand implementation that supports CanExecute logic (such as this one from MVVM Light).
Using a command will automatically disable any bound control (e.g. button or menu item) when CanExecute is false. You can then have all the logic for controlling your commands grouped in one place, including validation that will only allow OK to be clicked when your object is in a valid state.
If you just want to go the standard WPF (non MVVM) route, you could add something like this in your window's constructor
public MyView()
{
....
Ok_Button.Command =
new RelayCommand(() => DialogResult = true, // just setting DialogResult is sufficient, no need to call Close()
// put the required validation logic here
() => dxSpinEdit.Value > 0 && dxSpinEdit.Value < 10);
Cancel_Button.Command = new RelayCommand(() => DialogResult = false);
// replace this with the actual event from SpinEdit
dxSpinEdit.ValueChanged += (s,e) => (OK_Button.Command as RelayCommand).RaiseCanExecuteChanged();
}
Yes I know it looks ugly 😀 - I'd suggest following the MVVM design pattern instead. When using MVVM, all of the command functionality belongs in your ViewModel.
Either way, you can then remove all the click and mousedown handlers from your buttons.
I'm using WPF
I want to auto-tab to the next texbox when 'MaxLength' is reached.
I found this code : XAML Trigger Auto-tab when MaxLength is Reached
And it's working. But the problem is, I can't delete text when the MaxLength is reached !
I can't change the actual text too.
Do you have an idea to allow me to modify, or delete text from a MaxLength reached textbox ?
My XAML :
<TextBox Grid.Column="0" Name="txtC1" Margin="5" MaxLength="7" PreviewKeyDown="txt1_PreviewKeyDown"></TextBox>
<TextBox Grid.Column="1" Name="txt2" Margin="5" MaxLength="12" PreviewKeyDown="txt2_PreviewKeyDown"></TextBox>
<TextBox Grid.Column="2" Name="txt3" Margin="5" MaxLength="12" PreviewKeyDown="txt3_PreviewKeyDown"></TextBox>
Code Behind
private void txt1_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
// Auto-tab when maxlength is reached
if (((TextBox)sender).MaxLength == ((TextBox)sender).Text.Length)
{
// move focus
var ue = e.OriginalSource as FrameworkElement;
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
The problem is that you are using the event on a keyDown and that means that when backspace or delete is pressed, the event is triggered but the text hasn't changed until the keyDown event is done, so the code will always validate with the same number of characters in the textBox and it will take one more character to type in the box to trigger the change of focus in your case.
You can do something like this instead
XAML
<TextBox Grid.Column="0" Name="txtC1" Margin="5" MaxLength="7" TextChanged="txt1_TextChanged"></TextBox>
<TextBox Grid.Column="1" Name="txt2" Margin="5" MaxLength="12" TextChanged="txt2_TextChanged"></TextBox>
<TextBox Grid.Column="2" Name="txt3" Margin="5" MaxLength="12" TextChanged="txt3_TextChanged"></TextBox>
Code
private void txt1_TextChanged(object sender, TextChangedEventArgs e)
{
if (((TextBox)sender).MaxLength == ((TextBox)sender).Text.Length)
{
// move focus
var ue = e.OriginalSource as FrameworkElement;
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
You can still do some keyDown event for something else e.g.: Allowing some key only like numbers or special numbers, but it is better to validate the text lenght with a textChanged event.
I resolved my own problem. Thanks to differents answers I got, I used them a little.
This is my new code behind :
private void txt1_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
// Auto-tab when maxlength is reached
if (((TextBox)sender).MaxLength == ((TextBox)sender).Text.Length)
{
if(e.Key != Key.Delete && e.Key != Key.Clear && e.Key != Key.Back && ((TextBox)sender).SelectionLength == 0)
{
// move focus
var ue = e.OriginalSource as FrameworkElement;
e.Handled = true;
ue.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
}
}
And it's working.
I'm trying to get my border focused after the user clicks on it.
Currently it is possible to focus the border via tabs, but via click would be way more convenient for the user.
<Border x:Name="BorderFileInfo" Focusable="True" BorderBrush="LightGray" BorderThickness="1">
<Grid Margin="3,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left">
<!-- CONTENT CTRL -->
</Grid>
</Border>
I saw in another post that there is a possability to catch the click event with an InputBinding but I don't know how to focus the border afterwards without using a command.
Stackoverflow: Why doesnt WPF border control have a mousedoubleclick event?
Is there an easy way to do that other than having to create commands ?
The app is pretty small so I don't want to use commands if I don't have to.
One easy way is to handle PreviewMouseDown or similar mouse events and set the focus:
private void Border_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Keyboard.Focus(sender as Border);
}
edit
note that you can create Click by handling PreviewMouseLeftButtonDown and PreviewMouseLeftButtonUp in this way:
_isdown =false;
private void Border_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_isdown =true;
}
private void Border_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if ( _isdown)
{
_isdown = false;
Keyboard.Focus(sender as Border);
}
}
I need to edit some hierarchical structure and I use TreeView with TextBoxes
Short example
<TreeView>
<TreeView.Items>
<TreeViewItem Header="Level 0">
<!-- Level 1-->
<TextBox Margin="5"
BorderThickness="1" BorderBrush="Black" />
</TreeViewItem>
</TreeView.Items>
</TreeView>
When I type in TextBox, +, -, letters and digits work fine, arrows work but when I press -, Level 0 item collapses and when I type *, nothing happens
How should I handle - and * to see them in TextBox as expected?
Edit:
- works if typed as Key.OemMinus but not from numeric keyboard as Key.Subtract
* works if typed as Shift+Key.D8 but not from numeric keyboard as Key.Multiply
finally solved the problem with Key.Subtract
I added handler to PreviewKeyDown on TextBox
<TextBox Margin="5" BorderThickness="1" BorderBrush="Black"
PreviewKeyDown="TextBoxPreviewKeyDown"
/>
on receiving Key.Subtract, KeyDown is marked as handled and then i manually raise TextInput event as explained in this answer (How can I programmatically generate keypress events in C#? )
private void TextBoxPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Subtract)
{
e.Handled = true;
var text = "-";
var target = Keyboard.FocusedElement;
var routedEvent = TextCompositionManager.TextInputEvent;
target.RaiseEvent(
new TextCompositionEventArgs
(
InputManager.Current.PrimaryKeyboardDevice,
new TextComposition(InputManager.Current, target, text)
)
{
RoutedEvent = routedEvent
});
}
}
I can suggest a keydown event for the textboxes that you have.
<TextBox Margin="5" KeyDown="TextBox_KeyDown"
BorderThickness="1" BorderBrush="Black" />
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
TextBox txt = sender as TextBox;
if(e.Key == Key.Subtract)
{
txt.Text += "-";
txt.SelectionStart = txt.Text.Length;
txt.SelectionLength = 0;
e.Handled = true;
}
else if (e.Key == Key.Multiply)
{
txt.Text += "*";
txt.SelectionStart = txt.Text.Length;
txt.SelectionLength = 0;
e.Handled = true;
}
}
It's not a good solution but it works. If you have any other "problem" keys, you can add an if to the event.
SelectionStart and SelectionLength are for positioning cursor at the end of textbox. And e.Handled = true; does prevent the default behaviour.