I have a Module,Within the module .I need two Ribbon buttons "Create" and "Edit".Both these buttons point same View and ViewModel.The only way i can distinguish these is using the command parameter property part of Ribbon Button.I am using Navigate View to move to the View.I want to pass additional parameter to ViewModel constructor saying the invoke is from Create or Edit.Any suggestions??
RibbonButton has a Tag property:
http://msdn.microsoft.com/en-us/library/microsoft.windows.controls.ribbon.ribbonbutton.ASPX
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.tag.ASPX
When defining the buttons, you can set Tag property for each ribbon button. You can then extract Tag value in your event handler and react accordingly.
I would bind Create and Edit buttons two different Commands e.g. CreateCommand and EditCommand. I would pass any additional details about the caller in the corresponding Execute methods of the Command.
Sample Code:
void CreateCommandExecute(object o)
{
YourMethod("Create", o);
}
void EditCommandExecute(object o)
{
YourMethod("Edit", o);
}
void YourMethod(string caller, object commandParameter)
{
// Your logic goes here
}
You need create two diferentes Commands in your ViewModel:
1- CommandEdit --> Asingned the CommandProperty button Edit by binding;
2- CommandCreate --> Asingned the CommandProperty button Create by binding.
Is not good idea shared logic in the shame command behavior.
Related
I am new to MVVM and can't find how to do the following:
I have MainPage.xaml and ElementOnePage.xaml
When somebody double tap an element of the main page, I want to display the ElementOnePage.
MainPage display a list, ElementOnePage display the detail
My MainPage DataContext is of type ElementViewModel
1) Should my ElementOnePage DataContext also be the same ?
2) I am using QueryString parameters to pass the information about which element has been selected.
However when I retrieve the element in the OnNavigatedTo(NavigationEventArgs args) function, this is too late.
I tried defining the DataContext of the page in this method, but it didn't work.
So how can I have a page that do the expected behavior while using effectively data binding ?
I have used MVVMLight for my WP7 apps. MVVMLight uses behaviors for command binding.
Create a RelayCommand in your MainPageViewModel, call it say NavigateToElementOneCommand.
Create a EventToCommand behavior on the ListBox, and bind it to the NavigatToElementOneCommand.
(Assuming that MainPageViewModel is set as MainPage's DataContext).
In NavigateToElementCommand, write the code to navigate to the ElementOnePage.XAML.
within my current project file I have a user control that has a storyboard animation applied to the control. When a button is clicked in the page the storyboard starts and basically visually presents the control to the user. The storyboard resides in the current page as a resource
<navigation:Page.Resources>
<Storyboard x:Name="PreferncesOpen">....</Storyboard x:Name="PreferncesOpen">
</navigation:Page.Resources>
Within the page I have button that I have a click event on that starts the storyboard
private void btnOpenPreferences_Click(object sender, RoutedEventArgs e)
{
preferencesPanel.Visibility = System.Windows.Visibility.Visible;
PreferncesOpen.Begin();
}
Within the userControl (preferencesPanel) I have a button that when clicked needs to close/collapse the user control. I plan to do this using Visibility.collapsed. I assume that I need to use routed commands since the button is within the user control but the actions need to be called within the page that contains the control? I'm still new to routed commands and I assume this is the correct approach. I'm just unsure how to click on a button within the user control and have it modify or execute commands that would impact how the page (in which this control resides) may change or for that part affect other elements within the page? For example when the button is clicked within the user control I would like the visibility of the user control to be set to collapsed. I also would like to have the width of one of the grid columns within the main page re-size. I have done this in the past using the code behind for the page but I am trying to separate some of this and I thought routed commands would be the way to go?
I'd greatly appreciate any tips.
Thank you in advance
The title is a bit misleading, you're asking about commands rather then routed events if I understand you correctly.
Here's an example of using a DelegateCommand<T> from the Prism library; It happens to be my personal preference.
Markup :
<Button x:Name="MyButton" Content="Btn" Command="{Binding DoSomethingCommand}"/>
Code-behind* or ViewModel :
(* if you're not using MVVM make sure to add MyButton.DataContext = this; so you're sure that the button can databind to your code behind effectively)
public DelegateCommand<object> DoSomethingCommand
{
get
{
if(mDoSomethingCommand == null)
mDoSomethingCommand = new DelegateCommand(DoSomething, canDoSomething);
return mDoSomethingCommand;
}
private DelegateCommand<object> mDoSomethingCommand;
// here's where the command is actually executed
void DoSomething(object o)
{}
// here's where the check is made whether the command can actually be executed
// insert your own condition here
bool canDoSomething(object o)
{ return true; }
// here's how you can force the command to check whether it can be executed
// typically a reaction for a PropertyChanged event or whatever you like
DoSomethingCommand.RaiseCanExecuteChanged();
The argument that's passed to the above function is the CommandParameter dependency property (in Prism it's an attached property as well as the Command property if memory serves me right).
When it's set, you can pass a value of your choosing to the command that you wish to execute.
Hope that helps.
This is my first attempt at MVVM. My application's core is loosely based Josh Smith's msdn article. And I am also using the mvvm light framework.
I have a main window containing a command list area and a workspace area which shows usercontrols/views as tabitems, each usercontrol has a corresponding viewmodel. The mainWindow also has a viewmodel containing my command list, and the workspace viewmodels have a base workspace viewmodel.
My default view has a master datagrid, of MappingSets, that can have one selected item. The commands launch new tabitems with views that handle MappingSet detail based on that selected item. I have a View/ViewModel that, depending on the command used should return either a tabitem for creating a new MappingSet with no existing data, or a tabitem containing the detail of the selected item for editing, or a tabitem containing detail the selected item as the base for a new MappingSet.
Having Set the scene, what I have not managed to work out is command dependent way to pass parameters, such as the identifier of the selected MappingSet object, to instantiate my viewmodel in one of the three states mentioned above? For instance would the mvvmlight messenger be appropriate for this task?
This is a perfect scenario for the messenger/eventaggregator. However, your message chain might be a bit convoluted. From what I'm understanding, your Main window holds a list of commands (like a menu or a ribbon). Here is how I see the chain of events.
You select a MappingSet from the datagrid, this causes a MappingSetSelected message to be fired (with a payload of the selected MappingSet)
The main window listens for that message and stores the currently selected MappingSet
When the user clicks the button a "EditMappingSet" or "CreateNewMappingSet" message is fired (or if the Window is responsible for creating the new views, it creates them itself).
If there are only three options, you could have them binding to three different commands and within the commands do the passing of your self-defined variable.
private RelayCommand _openMappingSetCommand;
//Command that one of your options is bound to
public ICommand ViewMappingSetOption1
{
get
{
if (_openMappingSetCommand == null)
{
_openMappingSetCommand = new RelayCommand(param => this.DoTabRequest("your parameter");
}
return _openMappingSetCommand ;
}
}
// Method that creates your viewmodel
private void DoTabRequest(parameterType parameter)
{
WorkspaceViewModel viewModel = null;
if (viewModel == null)
{
viewModel = (WorkspaceViewModel)Activator.CreateInstance(typeof (viewModelType), parameter);
this.Workspaces.Add(viewModel);
}
this.ActiveWorkspace = viewModel;
}
Then allow for that parameter on the constructor of your viewmodel and do whatever else you need based on that.
alt text http://www.freeimagehosting.net/uploads/abbcae9cd3.png
I want to create a listbox like the one shown in the image,
i just dont know how will i get the button(the red close button) click event for each item in the listbox
Can anyone point me to a good tutorial on this
Thanks
Create a button as usual, with a Click handler:
<Button Click="MyClickHandler">...</Button>
Now, in your click handler, you have the sender argument, which will contain the button that was clicked. You want the item that the button belongs to, though. First, you need to the ListViewItem that contains the button. There's several implementations of how to find a visual ancestor around, here's the first result I found. Add that extension method to a static class somewhere. So now your click handler looks like this:
private void MyClickHandler(object sender, RoutedEventArgs e)
{
ListViewItem parent = ((DependencyObject)sender).TryFindParent<ListViewItem>();
}
Now you need to retrieve the item that goes with this ListViewItem. This, thankfully, is much simpler (though I have no idea what it is, since your post doesn't say):
object ItemRelatedToButton = TheListBoxInQuestion.ItemContainerGenerator.ItemFromContainer(parent);
Replace object with the type that your ListBox actually contains, and the names with ones that are actually relevant. At this point, you can now interact with the item that the button is "attached" to.
You may also want to make sure parent isn't null, just in case something weird happened, and in theory you should make sure ItemRelatedToButton isn't null either.
If you don't want to write code behind, like MVVM would suggest, you have two choices:
1. if the control in your datatemplate supports ICommand, send the DataContext as the CommandParameter. Then the parameter will be passed into you command execute method.
2. If the control doesn't have an ICommand property, create an attached property, in the PropertyChangedCallback call back, your can hook a command to your clicked event. Then again, in Xaml you can pass the Datacontext as the CommandParameter.
Sorry for not elaborating further, but if you search for MVVM, Command and Attached, you should find tons of detail informations.
This button click method launches a Window called "(assemblyname).Reports" when a button with Content "Reports" is clicked:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)e.OriginalSource;
Type type = this.GetType();
Assembly assembly = type.Assembly;
Window window = (Window)assembly.CreateInstance(String.Format("{0}.{1}", type.Namespace, button.Content));
window.ShowDialog();
}
But I want the Content attribute value of the button to be able to change, e.g. it might change to "Stock Reports" but I still want the clicking of the button to launch "(assemblyname).Reports".
Is there a way to add attributes to the button tag, e.g. "TheWindowFileName"?
<Button x:Name="btnReports" Content="Stock Reports" TheWindowFileName="Reports"/>
If not, how else can I add additional information to my button elements which I can read and process in code behind?
Certainly you can use attached properties to add extra attributes to XAML elements, but for what you need you could probably just use the existing Tag property:
<Button x:Name="btnReports" Content="Stock Reports" Tag="Reports"/>
Using Attached Property here can be an overkill but instead you can try to encapsulate your button behavior in a Command and pass the data you want to use in the command as a CommandParameter. That should do the trick.