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.
Related
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!
I have my groupbox defined inside a window as follows
<ScrollViewer>
<Grid Name="gridMain">
<GroupBox x:Name="grp" Header="Group" Margin="0,71,0,0">
<Grid Margin="0,69,0,0" x:Name="gridmain">
<CheckBox x:Name="ChkShow" Content="Hide Controls" IsChecked="True" Checked="ChkShow_Checked" Unchecked="ChkShow_Unchecked" Margin="27,52,76,38"></CheckBox>
<Label x:Name="lblUsername" Content="Username" Margin="21,10,107,68" Visibility="Hidden"></Label>
</Grid>
</GroupBox>
</Grid>
</ScrollViewer>
This is my code to show/hide the control
private void ChkShow_Unchecked(object sender, RoutedEventArgs e)
{
lblUsername.Visibility = Visibility.Hidden;
}
private void ChkShow_Unchecked(object sender, RoutedEventArgs e)
{
lblUsername.Visibility = Visibility.Visible;
}
But I am unable to find the control it is getting as null so how can I over come this issue
It's all about order.
The CheckBox is created first. The event handlers are attached and the value is set to True. The event handler fires and tries to call the not-yet-created Label. Hence the Label is having the value null.
If you move the label to above the CheckBox it does work. It will also work if you would attach the event handlers later on, for example in the OnLoad method.
I faced a same issue.
Actually checkbox event fire before label control initialize.
So you need to check first control is initialized first, means control not equal to null.
Or you can directly set visibility using binding(need bool to visibility converter) or you can set visibility using data trigger.
<Label x:Name="lblUsername" Content="Username" Margin="21,10,107,68" Visibility="{Binding path=IsChecked, ElementName=ChkShow, Converter={StaticResource converter}}"></Label>
Here is link for bool to visible converter http://wpftutorial.net/ValueConverters.html
I have created a button using XAML and have defined some simple properties for it.
<Button Name="btnNext" Grid.Row="1" Content="PARA" Width="200" Grid.Column="1" Background="#FF2D2D2D" HorizontalAlignment="Right" FontSize="40" Height="380" BorderThickness="0" />
It happens that when I click on the button or put the mouse over, it changes color.
I have tried to escape this behaviour in the btnNext_Click method but it does not affect anything.
private void btnNext_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button != null)
{
button.Background = new SolidColorBrush(hexToColorConvertor("#FF2D2D2D"));
START_POINT += (uint)NUMBER_OF_BUTTONS1;
ReadFile(START_POINT);
}
}
Does anyone have any idea how to resolve this?
In XAML, button have default style for different states like Normal, MouseOver, Pressed etc..
Whenever button moves from one state to another, it changes its look using default style obviously. You can find more information related to default style here
Now, If you want to override this default behavior, you can do it easily with Expression-blend. More of this can be found here and here
Hope this information will help you.. :)
I have a function I would like to run on after update of a lot of different text boxes, is it possible to listen for a generic after update event rather than the specific events?
So rather than 100 individual calls to the function, just one listener?
Edit: It would appear we are using a combination of MVVM and traditional code behind.
Here is one of the textboxes:
<TextBox Text="{Binding APhaseFrom}" x:Name="txtFromWhereA" TabIndex="26" HorizontalContentAlignment="Center" HorizontalAlignment="Left" Height="48" TextWrapping="NoWrap" VerticalAlignment="Top" Width="261" FontSize="26" FontWeight="Bold" BorderBrush="Black" BorderThickness="1" Margin="289,656,0,0" GotMouseCapture="txtFromWhereA_GotMouseCapture" GotFocus="txtFromWhereA_GotFocus" Grid.Row="3" />
The code from the view Model:
public string APhaseFrom
{
get { return new string((char[])_f.Rows[1].GetValue("Alpha09")); }
set
{
if (value.Length <= 35)
{
_f.Rows[1].SetValue("Alpha09", value);
}
else
{
MessageBox.Show("Error: String length Longer than 35 Characters.");
}
}
}
We also are using some commands for other processes:
public ICommand Updatesql
{
get;
internal set;
}
private void CreateUpdatesql()
{
Updatesql = new RelayCommand(UpdatesqlExecute);
}
private void UpdatesqlExecute()
{
_f.Update();
}
Should I be using commands or just link the events to functions in the viewmodel?
Since you are using WPF, and if I understand your problem correctly, then the RoutedEvents that WPF uses may help you here. Essentially, events like the LostFocus event of a TextBox will bubble up your UI hierarchy and can be handled by a common parent control. Consider this snippet of XAML and codebehind:
<StackPanel TextBox.LostFocus="TextBoxLostFocus">
<TextBox></TextBox>
<TextBox></TextBox>
<TextBox></TextBox>
</StackPanel>
Codebehind:
private void TextBoxLostFocus(object sender, RoutedEventArgs e)
{
MessageBox.Show("Lost Focus!");
}
You will find that the event handler is called for any of the three textboxes when focus is lost. The sender parameter or e.Source can be used to find the textbox that fired the event.
This pattern holds true for any RoutedEvent, so things like Button.Click or TextBox.TextChanged and many more can be caught in this manner.
Really and truthfully you should be using a single design pattern... ie MVVM when writing WPF applications, each textbox would be bound to a property which implements the INotifyPropertyChange interface.
In the setter of each property you would essentially update the value, fire a property changed event and then either make a call to your method or simply add an event handler on the view model for the PropertyChanged event.
Also... MessageBox.Show is a bad idea in your view models, its hard to unit test it.
Update
I removed my previous ideas because I now understand more clearly what you are looking for.
But you definitely need to use the LostFocus event.
<TextBox Text="{Binding APhaseFrom}" x:Name="txtFromWhereA" LostFocus="OnLostFocus" />
I have a class MyWindow which inherits from Window. Within MyWindow, I have the following method to execute once my OK button is clicked:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
var be = NameBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
this.Close();
}
XAML:
<Button Content="OK"
Click="OKButton_Click"
HorizontalAlignment="Left"
Margin="175,473,0,0"
VerticalAlignment="Top"
Width="75"
RenderTransformOrigin="-0.04,0.5"/>
In a separate class where I initialize my UI window, I say
MainWindow window = new MainWindow(ViewModel);
window.Show();
However, as soon as window.Show() is executed, the subsequent code is executed and I cannot actually interact with my window to do what I need to do. I feel like this is just a misunderstanding in how to actually use WPF in a larger context...any help?
Window.ShowDialog is what is needed to view the page. But one doesn't get the binding information as you did; which should be changed as well.
When the textbox loses focus it will update the binding so the code
var be = NameBox.GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
is not needed. (Is this a leftover form winform programming?) So I suggestion one not update a binding as such.
The only possible thing to do if the binding is not updated is to change the binding to use the mode of TwoWay which ensures a back and forth data transfer between the variable bound to and the textbox on the screen.