wpf button click - wpf

I Have a WPF app with 5 pages. On my main window I have 5 buttons. What I would like to do is click button 1 to open page 1 in a frame on the main window. I dont want to use a navagation window. Should I use some kind of binding? I would like to use xmal, the less code the better. Thanks in advance I'm in the learning stages!

You could set your buttons' Click event handlers to call Frame.Navigate(Uri) with their respective page.
In XAML:
<Frame Name="myFrame"/>
<Button Name="buttonPage1" Click="OnClickPage1">
Page1
</Button>
Then in the code behind:
void OnClickPage1(object sender, RoutedEventArgs e)
{
myFrame.Navigate(new Uri("page1"));
}

I assume that the logical follow-on from your comments is that pressing button 2 will open page 2 etc.
My recommendation, and this goes for all WPF development, is to adopt MVVM. It will give you a lot more flexibility and testability.
To implement your problem in MVVM:
Create ViewModels for each of your views, and one for your Main window
Each ViewModel becomes the DataContext for its respective View.
In the MainWindowViewModel implement 5 ICommand properties and bind the Command property on the button to each corresponding ICommand properties on the MainWindowViewModel.
On the main window, I am not sure if you are implementing a Frame control, but I would suggest using a ContentControl, bind the Content property on the control to some property of type Object on the MainWindowViewModel.
In the execution of each of the ICommand objects, you would set the content property on the MainWindowViewModel to the matching ViewModel for that button.
In the MainWindowView.xaml you would need to implement a series of DataTemplates which map the ViewModel to a View:
<DataTemplate DataType="{x:Type Page1ViewModel}">
<AdornerDecorator>
<views:Page1View DataContext="{Binding}"/>
</AdornerDecorator>
</DataTemplate>
I would suggest that you look at using one of the many MVVM frameworks available.
MVVMFoundation - light weight, bare minimum implementation
MVVMLight - heavier framework
Caliburn - seems to have a lot of additional functionality
Implementing a full framework might seem like a lot of extra work but it will be worth it in the long run, more testable, more maintainable.

Related

Use properties of the base control that is inside the UserControl

How can I use the properties of the controls that are inside a user control without having to use DependencyProperty?
Since, if for example I want to use all the properties of a button, I would have to declare all these?
And if there is another way without user control and it is the correct one, I would appreciate it if you answered it. (Google translator, sorry)
UserControl:
<UserControl x:Class="UserControls.UserControl01"
...
>
<Grid>
<Button x:Name="uc_btn" />
<TextBox x:Name="uc_txt" />
<DataGrid x:Name="uc_dtg" />
</Grid>
</UserControl>
Code using the UserControl:
<Window x:Class="UserControls.wnd02"
...
>
<Grid>
<local:UserControl01 uc_btn.Background="Red" uc_txt.Margin="10" uc_dtg.BorderThickness="5" Margin="90" />
<local:UserControl01 uc_btn.Background="Green" uc_txt.Margin="25" uc_dtg.BorderThickness="20" Margin="5" />
</Grid>
</Window>
It is not usual to do what you are asking.
Let's consider a usercontrol which is intended to work as if it is one single control. For example a time picker. This contains two sliders which increase/decrease hour and minute. You can also overtype in the hour and minute textboxes and there's a : between the two textboxes.
This usercontrol is all about the one property though. Time. You don't care what the minutes background is externally. If this changes it's internal to the usercontrol.
In this scenario you'd usually add a TimeSpan dependency property to the usercontrol and this is the only thing anything external to it uses.
Pretty much all commercial WPF development uses the MVVM pattern and that TimeSpan would be bound to a property in the parent view's viewmodel.
That's one scenario.
Another is where a usercontrol encapsulates a bunch of UI which is then re-usable.
Styling has scope so when you apply a style to say a Button in a window then that would apply to any Buttons in a usercontrol within it. Setting their properties.
There are also certain dependency properties marked as "inherits" whose values propogate down the visual tree.
One such is DataContext and it is this which most teams would use to deal with properties within a usercontrol.
Using MVVM there would be a MainWindowViewModel.
That would have (say ) a ChildUserControlViewModel property. That would be associated with usercontrol using a datatemplate specified datatype.
You'd then bind properties of whatever is in a usercontrol to properties of ChildUserControlViewModel or properties of MainWindowViewModel using RelativeSource binding.
ViewModel first is a common navigation and composition pattern for WPF. You should be able to find numerous blogs explain it better than I can in a SO post.
Here's one:
https://social.technet.microsoft.com/wiki/contents/articles/30898.simple-navigation-technique-in-wpf-using-mvvm.aspx

Adding controls dynamically in WPF MVVM

I am working on a dynamic search view wherein clicking a button should add a new row containing 3 combobox and 2 textboxes.
How should I go about doing this?
If you really want to do mvvm , try to forget "how can I add controls". You don't have to, just think about your viewmodels - WPF create the contols for you :)
In your case lets say we have a SearchViewModel and a SearchEntryViewmodel.
public class SearchEntryViewmodel
{
//Properties for Binding to Combobox and Textbox goes here
}
public class SearchViewModel
{
public ObservableCollection<SearchEntryViewmodel> MySearchItems {get;set;}
public ICommand AddSearchItem {get;}
}
Till now you dont have to think about usercontrols/view. In your SearchView you create an ItemsControl and bind the ItemsSource to MySearchItems.
<ItemsControl ItemsSource="{Binding MySearchItems}"/>
You see now all of your SearchEntryViewmodels in the ItemsControl(just the ToString() atm).
To fit your requirements to show every SearchEntryViewmodel with 3Comboboxes and so on you just have to define a DataTemplate in your Resources
<DataTemplate DataType="{x:Type local:SearchEntryViewmodel}">
<StackPanel Orientation="Horizontal">
<Combobox ItemsSource="{Binding MyPropertyInSearchEntryViewmodel}"/>
<!-- the other controls with bindings -->
</StackPanel>
</DataTemplate>
That's all :) and you never have to think about "how can I add controls dynamically?". You just have to add new SearchEntryViewmodel to your collection.
This approach is called Viewmodel First and I think it's the easiest way to do MVVM.
One option is that you can create TextBoxes and comboboxes in backend by creating a new instanse.
But the better option is that you can create one usercontrol which contains All texboxes and comboboxes which you want to add and in which format you want.
After creating when the button is pressed you can create a instace of this usercontrol and set it in the grid or any other control by using SetValue property of the control.
If you are new to WPF and MVVM this read this blogs to understand this.
https://radhikakhacharia.wordpress.com/2012/06/01/wpf-tutorial-3/
https://radhikakhacharia.wordpress.com/2012/02/13/model-view-viewmodel/
If you are new to both MVVM and WPF, there is a really wonderful video tutorial on how to
architect a C# / WPF / MVVM application by Jason Dollinger which is available here on lab49. All of the sourcecode he developes in this amazing video is available also right here on lab49.
After watching it, you will not have any problems developing your search view for sure.

Dynamically bind Views into a ContainerControl with MVVM

I've been learning the MVVM pattern with Josh Smith's article and I want to create a classic layout with some links to the right (managed with commands) so when I click one I can show my view to the right into a tab control (inside it there is a ContentControl).
This is simple when I use a DataTemplate with the specific View and ViewModel I want to show on screen like this.
<!-- this section into my MainWindow's resources file -->
<DataTemplate xmlns:vm='clr-namespace:WpfFramework.ViewModels'
xmlns:vw='clr-namespace:WpfFramework.Views'
DataType="{x:Type vm:MySpecificViewModel }" >
<vw:MySpecificView />
</DataTemplate>
But, I want something more generic. I mean that my mainWindow should not know a specific View nor a specific ViewModel. It should only know that it binds to some commands and has a tab control which shows "some view". Every sample including Josh Smith's article seems to have limited universe of views and viewmodels, that's great with a sample.
So, how can I tell my ContentControl that some view (with its corresponding viewModel) is gonna be there without being so specific (without "burning" into the mainView the concrete types)?
best regards
Rodrigo
PD. I have tryed with base a ViewModel and Base View but it doesn't seem to work.
In your main View, bind a ContentControl to a generic ViewModelBase property
<ContentControl Content="{Binding CurrentPage}" />
CurrentPage would be defined in the main ViewModel as a ViewModelBase object, and to switch pages you simply set CurrentPage to whatever you want.
So when you click on something like the HomePageCommand, the main ViewModel would execute CurrentPage = new HomePageViewModel(); providing that HomePageViewModel inherits from ViewModelBase.
I wrote something a little while ago that shows some samples here if you're interested

MVVM What is the way of updating a UI after a command?

I'm learning MVVM through a project and I got stuck on something simple.
I have a Button that updates a ListView. I have a command in the ViewModel that make the right things but I want to select the new row and get the focus on a TextBox after I click the Button.
The question is: How do I update my UI after executing a command?
If I need to change my windows Title when an operation have been made, I use a property on the ViewModel that is binded to the Window's title and it's changed when I need it but, I don't know how to get focus on a control when a command has been executed.
Thank you.
To select the new row, add a new property to your ViewModel ("SelectedItem" for instance), and bind the ListView's SelectedItem property to it :
<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">...
In the ViewModel, you just have to assign the new item to the SelectedItem property
To focus the TextBox, Mike's idea seems a good one
You could make an attached behavior. I'd suggest using the new Blend behavior framework, ie TriggerAction that contained this custom logic.
For your attached behavior you put on the button, give it a DP for an ICommand and maybe a DP of a ListView type.
On the "protected override void Invoke(object parameter)" of your TriggerAction, execute your ICommand, then you have reference to your ListView. Here you can do your custom code on it, like setting focus.
Your XAML may look something like this:
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Behaviors:CustomBehavior Command="CommandName" ListView="{Binding ElementName=myListView}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Button/>
I suggest looking at Mike Brown's ExecuteCommandAction behavior (download here), it's about almost 1/2 of what you need.
What about setting focus to the control in the code behind: textBox.Focus()
I consider everything you mention in your question to be GUI logic so I would add a Click event to the button to handle stuff that needs to happend in the GUI.
Hope this helps.
I think you need to use the Mediator pattern. Please see this:
Josh Smith's Mediator Prototype for WPF Apps
This is generally used in communicating with the View from the View-Model. Hope this helps.
In your case you need some way that the ViewModel notifies the View that it should set the focus on a specific control.
This could be done with an IView interface. The view implements this interface and the ViewModel can call a method of the View over this interface. This way you have still the View and ViewModel decoupled of each other.
How this can be done is shown here:
WPF Application Framework (WAF)
http://waf.codeplex.com

MVVM Tabcontrol change tab

I am developing an mvvm app with wpf. A requirement just got added on to block the user from changing tabs if a textbox has text.
What is the best way to do this completely in the viewmodel? I don't know how to block a tabitem because there is no dependencyobject command in the tabcontrol to tie into, do i need to roll my own tabcontrol and build an ICommand around the SelectionChanged event?
Should I simply (eegad..don't say it) put code in the code behind of the view in the SelectionChanged event?
Do I have an alternative that I haven't thought of?
You might consider binding each of the TabItems' IsEnabled property to a property in your ViewModel (e.g. ViewModel.TabsEnabled) and set that property to False when the textbox has text. That way, you'll be able to enable/disable those tabs from your ViewModel without having to have a code behind file for that particular view.
Which means you'll have something like the following in your view (assuming your ViewModel is a static class named ViewModel):
<TabItem IsEnabled="{Binding Source={x:Static local:ViewModel.TabsEnabled}}"/>
Then you just have to set the TabsEnabled property on the ViewModel when one of the textboxes has content; there are a couple of ways to do this, but if they are bound to your ViewModel you should have plenty of opportunities to listen for changes and set TabsEnabled as appropriate.

Resources