by Laurent Bugnion via Silverlight on 12/17/2009 4:49:31 PM
One of the MVVM Light Toolkit’s user requested that I add the possibility to pass the EventArgs of an event to the ICommand that it is bound to through the EventToCommand trigger. At first I was a bit reluctant because it seems like a transgression of the rule that says you should avoid to have too much knowledge about the UI layer in the ViewModel. For example, if you have a RelayCommand in the ViewModel that expects a MouseEventArgs, it kinds of binds you to a certain kind of UI element, which is not super clean.
That said, I also understand that in some cases it might be useful to get the EventArgs down in the ViewModel, which is why I decided to add this possibility (available from V3/alpha 3).
And in fact, as I was testing it, I just got another request from my good friend Laurent Kempé (one of the early and enthusiastic users of MVVM Light) to help use EventToCommand in the case of a drag&drop operation in Silverlight 4. That was the perfect test case for this new feature.
Note: Laurent wrote a post in French describing a drag&drop implementation.
The source code for this sample is available here. The MVVM Light Toolkit’s DLLs are also included (V3/alpha3). This code is for Visual Studio 2010 beta 2 and/or Expression Blend Preview for Silverlight 4.
You can optionally install the MVVM Light Toolkit V3/alpha3 from the Installing Manually page.
More info about the MVVM Light Toolkit is available on the Get Started page.
Let’s start by creating a new MVVM Light application in Silverlight 4. In the moment the process of installing the project templates is manual, but it should be easy enough if you follow these instructions.
We need to define a drop target for the files in the application. This can be done for just any UI element, so you can choose the main Grid (if you want the whole application to be a drop target) or any other element. In our case, to keep things simple, let’s define the main Grid as the drop target.
<Grid x:Name="LayoutRoot" AllowDrop="True" Background="#FF9F9F9F"> <TextBlock FontSize="36" FontWeight="Bold" Foreground="Purple" Text="{Binding DroppedFileContent}" VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" TextTrimming="WordEllipsis" /> </Grid>
/// <summary> /// The <see cref="DroppedFileContent" /> property's name. /// </summary> public const string DroppedFileContentPropertyName = "DroppedFileContent"; private string _droppedFile = "Drop file here"; /// <summary> /// Gets the DroppedFileContent property. /// Changes to that property's value raise the PropertyChanged event. /// </summary> public string DroppedFileContent { get { return _droppedFile; } set { if (_droppedFile == value) { return; } _droppedFile = value; RaisePropertyChanged(DroppedFileContentPropertyName); } }
public RelayCommand<DragEventArgs> HandleDropCommand { get; private set; }
public MainViewModel() { HandleDropCommand = new RelayCommand<DragEventArgs>(e => { System.Windows.MessageBox.Show("Drop"); }); }
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"
<i:Interaction.Triggers> <i:EventTrigger EventName="Drop"> <cmd:EventToCommand Command="{Binding HandleDropCommand, Mode=OneWay}" PassEventArgsToCommand="True" /> </i:EventTrigger> </i:Interaction.Triggers>
Now that we have the RelayCommand ready, let’s access the DragEventArgs and get the file content from there. In this sample example, we will accept TXT files, and display the first few words from the file content.
if (e.Data == null) { return; } var files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[]; // This works with multiple files, but in that // simple case, let's just handle the 1st one if (files == null || files.Length == 0) { DroppedFileContent = "No files"; return; } var file = files[0]; if (!file.Extension.ToLower().Equals(".txt")) { DroppedFileContent = "Not a TXT file"; return; } using (var stream = file.OpenRead()) { using (var reader = new StreamReader(stream)) { // Read the first line var line = reader.ReadLine(); DroppedFileContent = line; } }
Few notes about this code:
In the course of preparing this article, I noticed an issue in Visual Studio 2010 when I attempt to debug the HandleDropCommand implementation. Even with a breakpoint placed within the code, the debugger does not break. I am not sure right now what is the reason, and the code does get executed, but this complicates debugging of course. I am investigating and talking to Microsoft about that, but right now I am not sure where it comes from.
In the MVVM pattern, we generally try to avoid putting too much code in the code behind because it complicates the developer-designer workflow. Though I am not a puritan about that :) I think that EventToCommand and the new PassEventArgsToCommand property are reasonable steps to make UI interaction such as drag&drop even easier to code.
Hope you like it :)
Original Post: Silverlight 4: Drag&drop with EventToCommand
The content of the postings is owned by the respective author. Silverlight Feeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on Silverlight Feeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.