Surface 入门教程 2 (适合第一次接触Surface SDK的朋友)
这篇也是之前写的,最近忙于写论文,还没有来得及翻译,以后有时间的话会补上的 =.=
这一篇的信息量有点大,主要是还引用了两篇微软的教程作基础
Before starting this tutorial, I would like to recommend two tutorials from Microsoft about how to drag items from/into SurfaceListBox.
Dragging and Dropping Items Between SurfaceListBox Controls http://msdn.microsoft.com/en-us/library/ff727837
Dragging and Dropping Items from ScatterView Controls to SurfaceListBox Controls http://msdn.microsoft.com/en-us/library/ff727736
After these two tutorials, I believe you would have already established a basic understanding about drag and drop.
The rest of this section will give further introduction about make drag and drop works better in our applications.
Part 1. Dragging and dropping items from SurfaceListbox to ScatterView
This topic describes how to drag items from a SurfaceListBox control and drop them on a ScatterView control.
Step 1. Create a data item class for the items for SurfaceListBox control.
public class Person { private string name; private string id; public string Name { get { return name; } } public string ID { get { return id; } } public Person(string name, string id) { this.name = name; this.id = id; } }
Step 2. Define the two datatemplate objects in the Resources section of the main SurfaceWindow object, one for the SurfaceListBox and the other for the ScatterView.
<DataTemplate x:Key="ScatterViewItemDataTemplate" > <Border BorderThickness="2" BorderBrush="White" Margin="10"> <StackPanel Background="{DynamicResource {x:Static s:SurfaceColors.Accent3BrushKey}}"> <Label Content="{Binding Name}" HorizontalAlignment="Center VerticalAlignment="Center" FontSize="20"/> <Label Content="{Binding ID}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18"/> </StackPanel> </Border> </DataTemplate> <DataTemplate x:Key="SurfaceListBoxItemDataTemplate"> <Grid Width="190" Height="50"> <Label Content="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Gray" FontSize="20"/> </Grid> </DataTemplate>
Step 3. Define a ObservableCollection object to hold the data items for SurfaceListBox.
private ObservableCollection<Person> sourceItems; public ObservableCollection<Person> SourceItems { get { if (sourceItems == null) { sourceItems = new ObservableCollection<Person>(); } return sourceItems; } }
Step 4. Add some data items to the SurfaceListBox
protected override void OnInitialized(EventArgs e) { base.OnInitialized(e); DataContext = this; SourceItems.Add(new Person("Hammer", "111")); SourceItems.Add(new Person("Saw", "101")); SourceItems.Add(new Person("Pliers", "201")); SourceItems.Add(new Person("Square", "202")); SourceItems.Add(new Person("Wrench", "134")); SourceItems.Add(new Person("Plumb Bob", "234")); SourceItems.Add(new Person("Miter Box", "124")); SourceItems.Add(new Person("Knife", "432")); SourceItems.Add(new Person("Chisel", "688")); SourceItems.Add(new Person("Punch", "321")); }
Step 5. Creating the controls and Binding the Items
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="300"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <s:ScatterView Name="DropTarget" AllowDrop="True" Grid.Column="1" Background="Transparent" BorderBrush="White" BorderThickness="2" ItemTemplate="{StaticResource ScatterViewItemDataTemplate}" ItemsSource="{Binding}" s:SurfaceDragDrop.Drop="DropTarget_Drop"/> <s:SurfaceListBox Name="DragSource" Grid.Column="0" Width="210" Background="White" AllowDrop="True" ItemTemplate="{StaticResource SurfaceListBoxItemDataTemplate}" ItemsSource="{Binding Path=SourceItems}" PreviewTouchDown="OnDragSourcePreviewTouchDown" PreviewMouseLeftButtonDown="OnDragSourcePreviewTouchDown"/> </Grid>
Step 6. Define the drag cursor object for drag event in the Resources section of the main SurfaceWindow object.
<Style x:Key="CursorStyle" TargetType="{x:Type ContentControl}"> <Setter Property="ContentTemplate" Value="{StaticResource SurfaceListBoxItemDataTemplate}" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ContentControl}"> <Border Background="White" BorderBrush="Gray" BorderThickness="3"> <ContentPresenter Margin="0" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"> </ContentPresenter> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
Step 7. Setting the drag operation for the SurfaceListBox.
This part is as same as it in the Dragging and Dropping Items Between SurfaceListBox Controls tutorial, besides changing the TouchEventArgs parameter to InputEventArgs to enable the drag work with mouse.
private void DragSourcePreviewInputDeviceDown(object sender, InputEventArgs e)
Step 8. Setting the drop operation for the ScatterView
private void DropTarget_Drop(object sender, SurfaceDragDropEventArgs e) { DropTarget.Items.Add(e.Cursor.Data); ScatterViewItem svi = DropTarget.ItemContainerGenerator.ContainerFromItem(e.Cursor.Data) as ScatterViewItem; svi.Orientation = e.Cursor.GetOrientation(this); svi.Center = e.Cursor.GetPosition(this.DropTarget); svi.Width = 200; }
The first line of the code adds the drag item into the items collection of the ScatterView, and then a ScatterViewItem is created automatically for this data item.
The second line of the code gets the specified ScatterViewItem for this data item, so we are able to modify the angle and position of the item when the item being drop onto the ScatterView.
Part 2. Make control (i.e. ScatterView, SurfaceListBox) hold two different data templates
This part introduces how to enable the ScatterView control can hold different data templates for different data item.
Continue with the project of part 1.
Step 1. Create a new data item class
public class Animal { private string name; private string weight; private string age; public string Name { get { return name;} } public string Weight { get{ return weight;} } public string Age { get { return age; } } public Animal(string name, string weight, string age) { this.name = name; this.weight = weight; this.age = age; } }
Step 2. Define the DataTemplate objects for Animal in the Resources section of the main SurfaceWindow object.
Since the item in SurfaceListBox we can use the same style as Person (just shows name), we only need to define the template for ScatterView
<DataTemplate x:Key="ScatterViewItemDataTemplateForAnimal"> <Border BorderThickness="2" BorderBrush="Red" Margin="10"> <StackPanel Background="AliceBlue"> <Label Content="{Binding Name}" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20"/> <StackPanel Orientation="Horizontal"> <Label Content="{Binding Weight}" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18"/> <Label Content="{Binding Age}" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18"/> </StackPanel> </StackPanel> </Border> </DataTemplate>
Step 3. Define the ObservableCollection object for animal
public ObservableCollection<Animal> animalItems; public ObservableCollection<Animal> AnimalItems { get { if (animalItems == null) { animalItems = new ObservableCollection<Animal>(); } return animalItems; } }
Step 4. Add some data items for animal in the OnInitialized method
AnimalItems.Add(new Animal("Cat", "50", "4")); AnimalItems.Add(new Animal("Dog", "100", "5")); AnimalItems.Add(new Animal("Elephant", "1000", "3")); AnimalItems.Add(new Animal("Deer", "200", "5"));
Step 5. Add the new SurfaceListBox for Animal and Bind the items
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="300"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="300"/> </Grid.ColumnDefinitions> <s:ScatterView Name="DropTarget" AllowDrop="True" Grid.Column="1" Background="Transparent" BorderBrush="White" BorderThickness="2" ItemTemplate="{StaticResource ScatterViewItemDataTemplate}" ItemsSource="{Binding}" s:SurfaceDragDrop.Drop="DropTarget_Drop" /> <s:SurfaceListBox Name="DragSource" Grid.Column="0" Width="210" Background="White" AllowDrop="True" ItemTemplate="{StaticResource SurfaceListBoxItemDataTemplate}" ItemsSource="{Binding Path=SourceItems}" PreviewTouchDown="OnDragSourcePreviewTouchDown" PreviewMouseLeftButtonDown="OnDragSourcePreviewTouchDown"/> <s:SurfaceListBox Name="AnimalSource" Grid.Column="2" Width="210" Background="White" AllowDrop="True" ItemTemplate="{StaticResource SurfaceListBoxItemDataTemplate}" ItemsSource="{Binding Path=AnimalItems}" PreviewTouchDown="OnDragSourcePreviewTouchDown" PreviewMouseLeftButtonDown="OnDragSourcePreviewTouchDown"/> </Grid>
Step 6. Create template selector for choosing different templates for different data item
Create a new class named as . ScatterViewDataTemplateSelector
Include two namespaces shows below:
using System.Windows; using System.Windows.Controls;
And define the class as:
public class ScatterViewDataTemplateSelector: DataTemplateSelector { public override DataTemplate SelectTemplate(object item, DependencyObject container) { FrameworkElement element = container as FrameworkElement; if (element != null && item != null) { if (item is Person) return element.FindResource("ScatterViewItemDataTemplate") as DataTemplate; else if (item is Animal) return element.FindResource("ScatterViewItemDataTemplateForAnimal") as DataTemplate; } return null; } }
Step 7. Remove the ItemTemplate binding for the ScatterView, and change to
<s:ScatterView Name="DropTarget" AllowDrop="True" Grid.Column="1" Background="Transparent" BorderBrush="White" BorderThickness="2" ItemTemplateSelector="{StaticResource ScatterViewDataTemplateSelector}" ItemsSource="{Binding}" s:SurfaceDragDrop.Drop="DropTarget_Drop" />
Step 8. Include the definition of the ScatterViewDataTemplateSelector in the Resources section of the main SurfaceWindow object
Include the namespace for this project first:
xmlns:local="clr-namespace:Tutorial_2"
then add the code below to the Resources section:
<local:ScatterViewDataTemplateSelector x:Key="ScatterViewDataTemplateSelector"/>