WPF RelayCommand not firing on button click - c#

I'm inexperienced with both WPF and MVVM so i'm most likeley missing something but when I click my button the command isn't firing. I also have some menu controls on my page that i've setup the exact same way and when I click those, their commands work as expected.
I've tried attaching a click event handler to make sure the button is definitely being clicked which it is. I've also tried attaching a different command that works on my menu control which didn't work on the button.
<Button Grid.Row="1" Content="Add Note"
Command="{Binding InsertNoteCommand}"/>
public ICommand InsertNoteCommand { get; }
public MainViewModel()
{
InsertNoteCommand = new RelayCommand(InsertNote);
}
private void InsertNote()
{
Console.WriteLine("Note Inserted!");
}
I should also mention that i'm using MVVM Light

The debugging information is very useful to know but in the end I solved the problem by pointing the binding to the data context.
<Button x:Name="AddNewNoteBtn" Grid.Row="1" Content="Add Note"
Command="{Binding Path=DataContext.InsertNoteCommand, ElementName=_window}"/>
If anybody has comments on how I can improve this I would really appreciate it. Thanks!

Related

Xamarin Forms resize grid animation in MVVM

I can't figure it out how make a simple animation where after the click of a button a grid element changes it's size.
I work with MVVM so, like WPF if it's possible I prefere a "full xaml" solution (in my head a simple animation is charged to the view and not to the viewModel).
How can i do it?
Thank you
Maybe you are looking for something like below.
https://github.com/jsuarezruiz/Xamanimation#progress-animations
If not, please refer to the below documentation links for details about Animation.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/animation/simple
You can also write your own custom animations in Xamarin. Please refer below links.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/animation/custom
In Xaml you should bind your Button into the CommandParameter. To do this,
Step 1 - Give a x:name, step 2 bind it
<Button Command="{Binding MyButtonCommand}"
x:Name="myButton"
CommandParameter="{Binding Source={x:Reference myButton}}"/>
In your ViewModel:
public ICommand MyButtonCommand=> new Command(async(o) =>
{
Button myButton = (Button)o;
await myButton.TranslateTo(50, 0, 400);
});

WPF Button disables itself without binding or code making it so

I'll give some details below, but briefly I have a problem wherein a button in my WPF application will disable itself if I click somewhere else in the application. This button is linked to a Command but there is absolutely NOTHING bound to the IsEnabled property of the button and the Command CanExecute callback just sets e.CanExecute to true.
I saw this similar SO question (Weird problem where Button does not get re-enabled unless the mouse is clicked) but it was not helpful.
The application is simple and consists of a DockPanel divided into 4 parts. The left section contains a DataGrid and the right section contains a UserControl that also contains a couple DataGrids as well as the offending Button. It's so weird, but if I click on any row in the left DataGrid, the Button in the right section becomes disabled. The only way I can then re-enable it is to click on any row in either of the DataGrids in the right section!
Again, there IS absolutely nothing bound to the IsEnabled property of the button or any other code/markup implicitly in place that would allow this to happen.
Some relevant code snippets:
UserControl Command bindings:
<UserControl.CommandBindings>
<CommandBinding Command="cmd:DBScriptCommands.LoadScripts" CanExecute="cmdLoadScripts_CanExecute" Executed="cmdLoadScripts_Executed" />
<CommandBinding Command="cmd:DBScriptCommands.RunScripts" CanExecute="cmdRunScripts_CanExecute" Executed="cmdRunScripts_Executed" />
</UserControl.CommandBindings>
Button xaml:
<Button IsEnabled="True" x:Name="btnLoadScripts" Command="cmd:DBScriptCommands.LoadScripts">
<StackPanel HorizontalAlignment="Stretch">
<Image Source="/Images/folder-open.png" />
<TextBlock>Load Scripts</TextBlock>
</StackPanel>
</Button>
CanExecute for Command:
private void cmdLoadScripts_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
This has me baffled and any ideas are appreciated. If more information is needed, please let me know.
Edit 1:
Seems like it is something to do with the Command (still not sure what) - if I remove the Command parameter from the Button, the problem goes away - not useful because I want the button to trigger the Command, but interesting. In the CanExecute(), if I set e.CanExecute to false, the button is always disabled which makes sense. When it is set to true (like it is now) then I have the problem I've describe where it seems like something is setting it to false by magic sometimes.
Thanks

wpf making the same button show different info after multiple clicks

I'm creating something that has buttons, to show different info. I don't want to create a lot of buttons, but I don't know how to have the buttons show different information.
<Button x:Name="btn1"
Content=""
Click="btn1_Click"/>
<Button x:Name="btn2"
Content=""
Click="btn2_Click"/>
<Button x:Name="btn3"
Content=""
Click="btn3_Click"/>
<Button x:Name="btn4"
Content=""
Click="btn4_Click"/>
<Button x:Name="btn5"
Content=""
Visibility="Hidden"
Click="btn5_Click"/>
<Button x:Name="btn6"
Content=""
Visibility="Hidden"
Click="btn6_Click"/>
<Button x:Name="btnBack"
Content="Return to Main Menu"
Visibility="Hidden"
Click="btnBack_Click"/>
if you click btn1 from the main menu and click it again it will show info, but after clicking btn2 from the main menu and clicking btn1, it will show different info. I don't know how I could do that, and nothing i searched up has helped me so far.
Anything with a bunch of generic controls created by hand has a smell to it in WPF and your's is no different. This may sound bad, but in reality is something extremely good when it comes to WPF. Why? Because this means you get to learn how dynamic WPF is and you get to hopefully learn how to overcome the smell (at least for this situation).
Disclaimer: The pieces and ideas are here, but making a full working solution is not needed and may actually hinder the learning process.
You obviously have some dynamic buttons and you want to control visibility, functionality, and display. If we attempt to do these with buttons already created as you have, it gets nasty and dirty very quickly. So then what do we do? Well, let's create a small class to hold some of our button information.
public class MyButton : INotifyPropertyChanged
{
//Assume all properties did change notifications
public string Text { get; set; }
public ICommand Command { get; set; }
public Visibility Visibility { get; set; }
}
Now let's just assume you have either a ObservableCollection of these buttons in either a ViewModel or the Window itself.
You may be thinking, "well, that's great and all, but I am still having to bind all of this to the buttons I have." You would be wrong!
WPF has many containers. One of them being an ItemsControl. With that we can take our collection of MyButton and have it do all the leg work for us. Can you taste the cleanliness? Tasty isn't it?
<ItemsControl Items="{Binding YourCollectionOfMyButton}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Text}"
Command="{Binding Command}"
Visibility="{Binding Visibility}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Now there's some UI work to do to make it look pretty, but there you go. Now it doesn't matter what buttons you have, you don't need to do any work other than updating that collection.
How you want to deal with managing what buttons go in that collection is up to you, but do know that you are no longer jumping through the hoops to manage hardcoded X number of buttons. You can clear the collection, add 1 MyButton and be done with it. Need to add 30? You can!
You can do something like this
switch (btn.Text)
{
case "first":
btn.Text="second";
break;
case "second":
btn.Text="third";
break;
}
Maybe you can use an enum to your advantage.
An example would be:
public enum Action
{
Button1_Action1,
Button1_Action2
}
// In your form/window
private Action _currentAction = Action.Button1_Action1;
// After you click btn2
_currentAction = Action.Button1_Action2;
// After you click btn1
switch (_currentAction)
{
case Action.Button1_Action1:
// Do something
break;
case Action.Button1_Action2:
// Do something else
break;
}
Hope this gives you an idea :)

Execute command on textbox when hit enter key

I am new to WPF and I see the best pattern call MVVM. I have try to deep in it and I see that the command can only execute on a button or menuitem, etc. But I have a doubt how to execute the ViewModel command when I'm focusing on a textbox and hit the enter key when I finish my editing.
I have google this but I got nothing from all that answer. So hope all of you help me. How to execute command when hit the enter key in textbox?
In my opinion the easiest way is to use a KeyBinding, which allows you to bind a KeyGesture to an ICommand implementation.
In your case, you can write in your XAML something like this:
<TextBox AcceptsReturn="False">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding YourCommand}" />
</TextBox.InputBindings>
</TextBox>
So when your TextBox is focused and you press Enter, YourCommand will be executed.
I hope it can help you.
You can achieve your requirement using behaviors in WPF.
In XAML,
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<TextBox Text="MyText">
<i:Interaction.Behaviors>
<i:BehaviorCollection>
<EventToCommand EventName="TextChanged" Command="{Binding ViewModelCommand}">
**// You can provide other events to be triggered in the EventName property based on your requirement like "Focused" or "UnFocused".Focused event will be fired if you enter into edit mode and UnFocused event will be triggered if you press enter key.**
<i:BehaviorCollection>
</i:Interaction.Behaviors>
</TextBox>
In ViewModel.cs,
Public class ViewModel
{
private Command viewCommand;
public ViewModel()
{
viewCommand = new Command(CommandMethod);
}
public Command ViewModelCommand
{
get { return viewCommand }
set { viewCommand = value}
}
private void CommandMethod()
{
//This method will hit if you modify enter/delete text in the TextBox
}
}

How to build my own close button?

I have a wpf application with a MVVM. I am trying here to build my own close button. Based on this answer Creating a custom Close Button in WPF I added a button event handler in the View(xaml.cs) code. However, it is not recognizing the Close(); call (doesn't exist in the context - Can't resolve symbol).
Also I tried the other answer and added Command and CommandParameter into my button's xaml. But the function behind is not getting hits. In How to bind Close command to a button using the RelayCommand also my wpf is not recognizing RelayCommand. Then How can I use the RelayCommand in wpf said that I have to write it myself(really?). I remember there was a simple way similar to just set an event handler for the button and call Close();. But, how can I do that or why it is not working for me?
View code:
private void closeButton_Click(object sender, RoutedEventArgs e)
{
// I want to call close the whole app on button click
//Close(); is not recognized
}
private void performMainCloseButtonCommand(object Parameter)
{
// This doesn't get hits on button click
Window objWindow = Parameter as Window;
objWindow.Close();
}
Button XAML:
<Button x:Name="closeButton" RenderTransformOrigin="0.5,0.5" Padding="0" Margin="701,0,0,0" BorderThickness="0" Click="closeButton_Click" Command="{Binding MainCloseButtonCommand}" CommandParameter="{Binding ElementName = mainWindow}" Height="45" Width="45" >
<StackPanel Height="45" Width="45">
<Image x:Name="closeButtonImage" Margin="0" Source="/ProjectName;component/Resources/x.fw.png" Height="33"/>
<TextBlock Text="Close" Width="36" Padding="6,0,0,0" HorizontalAlignment="Center" Height="13" FontSize="10"/>
</StackPanel>
</Button>
Close isn't recognized in your event handler because there is probably no method called Close in your current class. If you want to call main window's close method you can use:
private void closeButton_Click(object sender, RoutedEventArgs e)
{
Application.Current.MainWindow.Close();
}
Above is not a good way to do this and does not align with MVVM pattern. Which relates to your second question. Without seeing remaining part of your code, its hard to say why command binding isn't working. My guess you haven't wired up the commands properly for it to fire. You will need to ensure that you have created your RelayCommand instance and your command properties are correctly set.

Categories

Resources