Xamly begin a storyboard when a RoutedCommand is called? - wpf

Is there a way to begin a storyboard wen an ICommand is executed WITH XAML?

RoutedCommands involve some code-behind, but this is definitely doable.
The simplest way is to add a CommandBinding to the parent control. Something like this:
<UserControl>
<UserControl.CommandBindings>
<CommandBinding Command="ApplicationCommands.Exit" Executed="HandleExit"/>
</UserControl.CommandBindings>
</UserControl>
Then in your code-behind event handler named 'HandleExit', invoke the storyboard either by name or from the Resources collection.
Let me know if you need some more clarification.

Related

Bind a Parent window's event to UserControl inner handlers with MVVM

I have a parent window that loads a usercontrol inside a ContentControl. The parent window has a ToolBar with some buttons (i.e. Save button). I'd like to assign those buttons commands that would be handled inside the usercontrol.
I need to manage my own ICommand commands from the usercontrol's ViewModel so, to summarize: The user clicks on the "Save" button (on the main window) so the button fires an event which the userControl handles to save the information within the control.
Is this possible?
There are two ways of doing it.
Using MVVM,
Since your window contains UserControl, you need to set up so that Window has reference to the UserControl ViewModel(assume it is called UserControlViewModel). If you have a command in the UserControlViewModel, you could bind to that command, by calling: UserControlViewModel.Command something like:
<Button x:Name="Save" Content="Save" Command="{Binding UserControlViewModel.SaveCommand}">
Use the event handler
Again, your window needs to have a reference to the class where the event handler is implemented. you could have the following in your Window XAML file:
<Button x:Name="Save" Content="Save" Clicked="SaveButtonClicked"/>
Then in your code behind,
private void SaveButtonClicked( .... sender, .... e)
{
UserControlClass.SaveData();
// or using command
UserControlClass.MyCommand.Execute()
}
OK, you are trying to bind a child element's command to a parent window. First give a name to the usercontrol (e.g. x:Name = MyUserControl) and write a public command in the usercontrol's datacontext/viewmodel (e.g. ICommand MyCommand). Now in the button do this
<Button x:Name="SaveButton" Command={Binding ElementName=MyUserControl, Path=DataContext.MyCommand} />
This will bind the save buttons command to the command inside the datacontext of child usercontrol :)
BTW, if you are looking for the other way around (i.e. binding child command to parent in mvvm) you will need to use FindAncestor. You can have a look on my codeproject article
regarding this :)
This sounds like a case where Routed Commands could work. For the routed command, set the Command of the tollbar button to "Save". Then in the user control, add a command binding that listens for the "save" command.
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.CommandBindings>
<CommandBinding
Command="Save"
CanExecute="SaveCommand_CanExecute"
Executed="SaveCommand_Executed"
/>
</UserControl.CommandBindings>
</UserControl>
In the code-behind's event handlers for the command binding, just locate the viewmodel and invoke the save command on it's viewmodel. If you want a more purist MVVM approach, you could try Josh Smith's approach to routed commands with MVVM.
Using this approach, as long as the user control has focus somewhere inside of it, then the save button's Save command will route to the user control's command binding and exec the save command.
I think this might accomplish your goal of decoupling the toolbar button from the dynamically loaded user control in the ContentPresenter.
Well after a while I come back to this question. I needed to communicate with my parent window so i decided to perform the view-viewmodel datacontext binding right from the parent window, mainly because I want the child viewmodel to attach to events fired from its parent and also I can fire events to the parent in order to show messages outside the child control.
I know I may not be using the MVVM pattern completly but I wanted to have more control over these features.

WPF: How to create events for custom usercontrols?

I have created a UserControl that consists of an ItemsCollection. Each item in this collection consists of a ListBox.
My application is represented by a Window, which contains this UserControl. I want to be able to manage events related to items inside the ListBox. How can I achieve this? (I am not sure if this is relevant or not, but the UserControl is in a assembly different from the application.)
Here's the code of the UserControl:
<UserControl
x:Class="UserControls.CalendarMonthViewControl.CalendarMonthView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignWidth="580"
d:DesignHeight="300"
xmlns:calendarMonthViewControl="clr-namespace:UserControls.CalendarMonthViewControl"
Name="CalendarMonthViewControl">
<Grid>
<ItemsControl
ItemsSource="{Binding ElementName=CalendarMonthViewControl, Path=Days}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="6" Columns="7" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type calendarMonthViewControl:Day}">
<Border>
<Grid>
<ListBox ItemsSource="{Binding Path=CalendarDayItems}" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
#vlad is on the right track.
There's a couple of options here. Both of them involve handling routed events.
To handle a routed event, you use the name of the owning class followed by the name of the event.
The first option is to simply handle the selection changed events (or some other ListBox event) on the Window class:
<Window ...
ListBox.SelectionChanged="OnChildListboxSelectionChanged">
...
</Window>
The second option (more typical approach) is to handle the ListBox events inside of the UserControl and then aggregate them in some way and fire an event at that level. This event is then handled by the Window. This event could be a routed event or a standard .NET event.
<UserControl ...
ListBox.SelectionChanged="OnChildListBoxSelectionChanged">
...
</UserControl>
Code behind for user control:
public event EventHandler<MyArgTypeEventArgs> ListBoxUpdated;
private void OnChildListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
// aggregate data and info
MyArgTypeEventArgs handler = ListBoxUpdated;
if (handler != null)
handler.Invoke(this, GenerateArgs());
}
The Window handles this event:
<Window ...
ListBoxUpdated="OnListBoxUpdated">
...
</Window>
This should give you something to start with.
I haven't used them much myself, but I think RoutedEvents would solve your problem. The events bubble up from your ListBox to the Window (or another element lower in the tree) where you can handle them.
edit: quoting from the link: To add a handler for an event using XAML, you declare the event name as an attribute on the element that is an event listener. The value of the attribute is the name of your implemented handler method, which must exist in the partial class of the code-behind file.
since UserControl inherits from UIElement, I'm guessing something like this would work (untested atm):
<UserControl
x:Class="UserControls.CalendarMonthViewControl.CalendarMonthView"
[...]
ListBox.NameOfEvent="EventHandlerName">
I don't think what you're trying to do is the right approach as it's creating unnecessary dependence between your views and means that your UserControl is not properly encapsulated.
In my opinion the nice solution would be to handle events in your UserControl's viewmodel and set up a relation between the viewmodel of your Window as needed, so that the views themselves are independent.

Binding Commands Without Using the DataContext [silverlight+prism]

Hello I have a problem with binding commands to button inside datagrid.
Here should be explanation but it doesn't explain everything.
http://msdn.microsoft.com/en-us/library/dd458928.aspx
What should be in classes in namespace Infrastructure?
Can somebody show me a really basic sample of using this?
not just parts of the code...
The Prism Commanding QuickStart - included with the Prism drop should provide the simple code example you are looking for.
All data-bindings go against the current DataContext unless specified otherwise. The DataContext is inherited down the tree of controls unless a control specifically picks a DataContext.
For example your Button might look like this and would look for the SaveCommand on whatever the DataContext has:
<Button Command="{Binding SaveCommand} />
Your button could also look like this if you wanted to bind to a command exposed on your classes code-behind:
<UserControl x:Name="UserControl">
...
<Button Command="{Binding SaveCommand, ElementName=UserControl}"
...
</UserControl>
Using DelegateCommand is just a way of implementing the ICommand you bind to and that should be visibile in the Prism QuickStart.

WPF - Handle an ApplicationCommand in the ViewModel

I bet this has been answered many times over, but...
For a simple situation where a button on a UserControl has its command property set to something like Find (ApplicationCommands.Find) how would the ViewModel handle that command? I usually see command handlers wired up with a CommandBinding that gets added to a CommandBindings collection on a UIElement, but my ViewModel doesn't derive from UIElement (should it?). The commands themselves don't expose events to notify when they've been executed, so where should I wire up to get that information?
EDIT: I'd like to use stock WPF to solve the problem if possible. I know there are many available frameworks for this sort of thing but would like to keep the code simple.
EDIT2: Including some sample code.
<UserControl>
<UserControl.DataContext>
<local:MyViewModel/>
</UserControl.DataContext>
<Button Command="Find"/>
</UserControl>
Where:
class MyViewModel
{
// Handle commands from the view here.
}
I could add a CommandBinding to the UserControl which would handle Executed, then call a hypothetical Find method in MyViewModel which does the actual work, but that's extra and unnecessary code. I'd prefer if the ViewModel itself handled the Find command. One possible solution would be to have MyViewModel derive from UIElement however that seems counter intuitive.
The purpose of commands is to decouple the code which generates the order from the code which executes it. Therefore: if you want tight coupling, you should better do it through events:
<UserControl ... x:Class="myclass">
...
<Button Click="myclass_find" .../>
...
</UserControl>
For loose coupling you need to add a CommandBinding to your UserControl:
<UserControl ... >
<UserControl.DataContext>
<local:MyViewModel/>
</UserControl.DataContext>
<UserControl.CommandBindings>
<Binding Path="myFindCommandBindingInMyViewModel"/>
</UserControl.CommandBindings>
...
<Button Command="ApplicationComamnd.Find" .../>
...
</UserControl>
(not sure about the syntax)
Or you can add a CommandBinding to your UserControl's CommandBindings in the constructor, taking the value from the ViewNodel:
partial class MyUserControl : UserControl
{
public MyUSerControl()
{
InitializeComponent();
CommandBinding findCommandBinding =
((MyViewModel)this.DataContext).myFindCommandBindingInMyViewModel;
this.CommandBindings.Add(findCommandBinding);
}
}

WPF - MVVM Command binding on Sub ViewModel

I've got a VehicleViewModel that has a sub ViewModel of NotesViewModel
public IManageVehicleNotesViewModel NotesViewModel { get; set; }
On the first activation of VehicleViewModel I activate the sub ViewModel.
NotesViewModel.Activate();
The activation calls a method to init a number of Commands, I've break pointed this and its being called.
CreateCommand = new DelegateCommand<object>(OnCreateCommand, CanCreate);
However although the TextBoxes are binding on the sub View (so the DataContext is in place) none of the commands are binding - I've tried to calling RaiseCanExecuteChanged on the commands but they don't disable, enable or call the methods as expected.
I don't know whether its relevant (as the TextBoxes are binding) but I'm associating the View and ViewModel using a ResourceDictionary as so ...
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:v="clr-namespace:GTS.GRS.N3.Modules.Vehicles.Views"
xmlns:vm="clr-namespace:GTS.GRS.N3.Modules.Vehicles.Model">
<DataTemplate DataType="{x:Type vm:ManageVehicleViewModel}">
<v:ManageVehicleView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ManageVehicleNotesViewModel}">
<v:ManageVehicleNotesView />
</DataTemplate>
</ResourceDictionary>
The commands on the top level VehicleViewModel work.
Has anyone experienced anything like this? Is it the order I'm doing things? Any help gratefully received!
Cheers,
Andy
Does the CreateCommand property trigger the PropertyChanged event ? If it doesn't, the UI won't be notified when you assign it...
Try to use a tool like Snoop to check whether the Command property of the button is set
Do this and check the output to see what is going on:
<UserControl …
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase" />
<Button Command="{Binding MyCommand,
diagnostics:PresentationTraceSources.TraceLevel=High}" … />
It should report what object it's actually trying to bind to, etc. Check your output window while you are running to see what is going on with that binding.

Resources