I have the following popup where a user is able to enter three fields and when they click 'ok'. The popup should simply disappear. As of now, when I click on the ok button, nothing happens, the popup just stays there, the same goes for when I click the 'Cancel' button, nothing happens either. What am I missing that when I press the 'OK' button, it does not disappear? Why are the buttons not doing anything when I click on them?
EDIT:
After placing a breakpoint on my ok button logic, I get a hit on that, however, I think my main question here is if there is a way for the popup to close after clicking on ok, hence, the user is done entering data.
As for the cancel button, it does not trigger when the breakpoint when clicking on the button.
XAML CODE
<Border Grid.Column="0" Margin="5"
Grid.Row="2">
<WrapPanel HorizontalAlignment="Right">
<Button x:Name="btnCancel" Command="{Binding Path=CloseCommand}"
Content="_Cancel" Margin="4,2" MinWidth="60"/>
<Button x:Name="btnOk" Command="{Binding Path=OKCommand}"
Content="_OK" Margin="4,2" MinWidth="60"/>
</WrapPanel>
</Border>
ViewModel Code
public event CancelHandler OnCancel;
public delegate void CancelHandler();
public ICommand CancelCommand
{
get { return new RelayCommand(c => OnCancelLock()); }
}
public ICommand OKCommand
{
get { return new RelayCommand(c => OnOKLock()); }
}
protected void OnOKLock()
{
var currentSetting = AppSession.Repository.Settings.Find(SettingQuery.ID == new ID("LockedOutDate"));
currentSetting[0].Value = LockedOutDate;
AppSession.Repository.Settings.Save(currentSetting[0]);
currentSetting = AppSession.Repository.Settings.Find(SettingQuery.ID == new ID("LockedOutBy"));
currentSetting[0].Value = LockedOutBy;
AppSession.Repository.Settings.Save(currentSetting[0]);
currentSetting = AppSession.Repository.Settings.Find(SettingQuery.ID == new ID("LockedOutFor"));
currentSetting[0].Value = LockedOutFor;
AppSession.Repository.Settings.Save(currentSetting[0]);
currentSetting = AppSession.Repository.Settings.Find(SettingQuery.ID == new ID("IsUsersLockedOut"));
currentSetting[0].Value = "1";
AppSession.Repository.Settings.Save(currentSetting[0]);
}
protected void OnCancelLock()
{
OnCancel();
}
The problem you have is right here:
<Button x:Name="btnCancel" Command="{Binding Path=CloseCommand}"
Content="_Cancel" Margin="4,2" MinWidth="60"/>
You defined your binding to be CloseCommand, but in your ViewModel code you wrote:
public ICommand CancelCommand
{
get { return new RelayCommand(c => OnCancelLock()); }
}
So either change it to CloseCommand in your ViewModel or CancelCommand in your XAML file.
Related
i want to put a TextBox, together with a Label and a SymbolIcon into a Button, so that the whole thing is clickable. at the start you can only see the label and the symbol. By clicking on the button, the label gets hidden and the textBox appears, where you can type some text. By clicking again the label comes up again with the new entered text and the TextBox disappears.
My problem is, that by setting the focus to the TextBox, the button (parent) also seems to get into focus, because everytime you press the spacebar, the Click Event of the button fires. I dont want this to happen, while the TextBox has focus.
XAML
<Button Click="ToggleTopic"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid>
<TextBlock x:Name="textBlockInfoTopic"
Text=""
HorizontalAlignment="Left"
Margin="100,0,100,0"/>
<TextBox x:Name="textBoxTopic"
PlaceholderText="enter Topic..."
HorizontalAlignment="Stretch"
Margin="100,0,100,0"
Visibility="Collapsed"/>
<SymbolIcon x:Name="symbolTopicButton"
Symbol="Add"
HorizontalAlignment="Right"/>
</Grid>
</Button>
C#
private void ToggleTopic(object sender, RoutedEventArgs e)
{
if (textBoxTopic.Visibility == Visibility.Visible)
{
//non edit mode
textBoxTopic.Visibility = Visibility.Collapsed;
textBlockInfoTopic.Visibility = Visibility.Visible;
symbolTopicButton.Symbol = Symbol.Add;
textBlockInfoTopic.Text = textBoxTopic.Text;
}
else
{
//edit mode
textBoxTopic.Visibility = Visibility.Visible;
textBoxTopic.Focus(FocusState.Programmatic);
textBlockInfoTopic.Visibility = Visibility.Collapsed;
symbolTopicButton.Symbol = Symbol.Go;
textBlockInfoTopic.Text = "";
}
}
I only want to prevent the triggering of the event through the spaceBar. The return key should trigger the event.
Thanks for helping me!
D.
From official document,
If a button has keyboard focus, pressing the Enter key or the Space key also raises the Click event. You generally can't handle low-level PointerPressed events on a Button because it has the Click behavior instead.
If you want to prevent SpaceBar from triggering the Click event, you could override OnProcessKeyboardAccelerators method of Button like the following.
public class MyButton : Button
{
protected override void OnProcessKeyboardAccelerators(ProcessKeyboardAcceleratorEventArgs args)
{
if(args.Key == VirtualKey.Space)
{
args.Handled = true;
}
base.OnProcessKeyboardAccelerators(args);
}
}
Usage
<local:MyButton Click="ToggleTopic"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid IsTapEnabled="False" >
<TextBlock x:Name="textBlockInfoTopic"
Text=""
HorizontalAlignment="Left"
Margin="100,0,100,0"/>
<TextBox x:Name="textBoxTopic"
PlaceholderText="enter Topic..."
HorizontalAlignment="Stretch"
Margin="100,0,100,0"
Visibility="Collapsed"/>
<SymbolIcon x:Name="symbolTopicButton"
Symbol="Add"
HorizontalAlignment="Right"/>
</Grid>
</local:MyButton>
I have a user control with two buttons (Add, Delete). When accessed from the main window, how do I know which button were being clicked?
btnAdd had a method while btnDelete has another method that should be invoked.
Create two separate Command for button add and delete in MainWindow
And you can bind your command in userControl like this:
<Button Command={Binding AddCommand}/>
and set the datacontext of Mainwindow to itself inside XAML or in a constructer
this.datacontext = this;
For more information on how to create Command see this and this
If I understand your issue correctly, you could cast the sender argument in the event handler:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button.Name == "btnAdd ")
{
//add button was clicked...
}
else if (button.Name == "btnDelete")
{
}
}
<Button x:Name="btnAdd" Content="Add" Click="Button_Click" />
<Button x:Name="btnDelete" Content="Delete" Click="Button_Click" />
I have code like this:
<Button x:Name="ExpandSearchCriteriaButton" Command="{Binding ExpandSearchCriteriaCommand}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeave">
<i:InvokeCommandAction Command="{Binding StaysOpenLeaveCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding StaysOpenEnterCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Popup StaysOpen="{Binding PopupStaysOpen, Mode=TwoWay}" IsOpen="{Binding PopupIsOpen, Mode=TwoWay}" PlacementTarget="{Binding ElementName=ExpandSearchCriteriaButton}">
//my content here
</Popup>
And now in C#:
private void execExpandSearchCriteriaCommand()
{
if (!PopupIsOpen)
{
PopupIsOpen = true;
}
else
{
PopupIsOpen = false;
}
}
private void execStaysOpenEnterCommand()
{
PopupStaysOpen = true;
}
private void execStaysOpenLeaveCommand()
{
PopupStaysOpen = false;
}
private bool _popupIsOpen;
public bool PopupIsOpen
{
get { return _popupIsOpen; }
set {
_popupIsOpen = value;
RaisePropertyChanged("PopupIsOpen");
}
}
private bool _popupStaysOpen;
public bool PopupStaysOpen
{
get { return _popupStaysOpen; }
set {
_popupStaysOpen = value;
RaisePropertyChanged("PopupStaysOpen");
}
}
The problem is that when my popup is opened by clicking
ExpandSearchCriteriaButton
then
MouseEnter
trigger should change my
PopupStaysOpen
property to true. BThat's unfortunately not happened (tested in console) because trigger basically isn't working when I hover my button and it should, because when popup is closed, it happens. Because of that, when I click button when popup is opened, my popup disappears for while and reappears and if after that I click button it's finally working what's not my target. I want it to close for the first, not second click.
I think, that behavior you see is correct. The trigger for Button doesn't work only if PopUp has StaysOpen=false(for StaysOpen=true it works), this means PopUp captures the mouse events for to be closed(set IsOpen to false) on first click. So if you set StaysOpen to false, the PopUp starts to catch mouse events.
When the window is opened, Abort is clickable, but all of the other buttons are not.
I put breakpoints at my getters:
public ICommand OkCommand
{
get { return _okCommand; }
}
and the button is disabled after it is called. I feel like I'm missing something obvious here. Is my binding not setup correctly? Or is it not being correctly initialized?
My ViewModel constructor:
[ImportingConstructor]
public MyViewModel(IMyViewModel view)
: base(view)
{
_okCommand = new DelegateCommand(OkHandler, IsValid);
_refreshCommand = new DelegateCommand(RefreshHandler, IsValid);
_testConnCommand = new DelegateCommand(TestConnectionHandler, IsValid);
}
My XAML for two of the buttons.
<StackPanel Orientation="Horizontal" Margin="0,14" HorizontalAlignment="Center" DockPanel.Dock="Bottom">
<Button Command="{Binding OkCommand}" Content="Ok" IsDefault="True" TabIndex="3" Margin="5,0"/>
<Button Content="Abort" IsCancel="True" TabIndex="4" Margin="0"/>
</StackPanel>
The second parameter of the DelegateCommand constructor is a Func that tells if the Command is executable. WPF uses this to determine if buttons, etc should be enabled.
I would check your IsValid Func / method whether it works okay, that is: returns true.
Some of the checkboxes on my form should not be able to be checked/unchecked by users. Is there a way for me to cancel the event before the checbox's Check event is triggered?
in winForms it was easy, just
public void cb_BeforeChecked(object sender, EventArgs e){
e.Handled = true;
}
but I cannot find anything like this in WPF...I figure you can probably do it, just need to do something fancy..
Thanks!
Why not just set IsEnabled="False"?
You can set IsHitTestVisible="False" to make it not respond to user clicks. Otherwise you can bind it to a command if viewmodel logic determines whether it is clickable.
<Grid>
<CheckBox IsHitTestVisible="False" Content="I cannot be clicked at all"/>
<CheckBox Command="{Binding DoSomethingCommand}" Content="I can be clicked if DoSomethingCanExecute returns true."/>
</Grid>
In your DataContext (Viewmodel or otherwise):
RelayCommand _DoSomethingCommand = null;
public ICommand DoSomethingCommand
{
get
{
if (_DoSomethingCommand== null)
{
_DoSomethingCommand= new RelayCommand(
param => DoSomething(),
param => DoSomethingCanExecute
);
}
return _DoSomethingCommand;
}
}
public bool DoSomethingCanExecute
{
get
{
return CheckboxShouldBeEnabled();
}
}
public void DoSomething()
{
//Checkbox has been clicked
}
This might be a bit of an overkill, but you could sub-class CheckBox and then override the OnClick() method.
Only setting IsHitTestVisible="False" just takes care of the Mouse, the users can still use the KeyBoard to tab to the CheckBox and change the value.
You should set both IsHitTestVisible="False" and Focusable="False" to disable the KeyBoard as well
You can have the check box disabled, and associate a style with the disabled check box, if the disabled look is a problem. As its already pointed in the previous posts, its good to have different looks for different states.