您好我试图将我的应用程序迁移到WPF,并且我试图尽可能多地保留MVVM。我的WinForm应用程序的以下屏幕相当容易创建,我没有Xaml和WPF这么好运。
我喜欢它是如何工作的,但我的目标是使用WPF重新创建它,或者以某种我尚未想到的方式映射,仍然满足将输入字段映射到我的基本要求现有的数据结构。
目前这就是我在Xaml中所拥有的。
<UserControl x:Class="ImportJobDataView"
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"
xmlns:kne="clr-namespace:FatigueMVVM"
xmlns:local="clr-namespace:FatigueMVVM.DragDropListBox"
mc:Ignorable="d" d:DesignHeight="350" d:DesignWidth="447">
<Grid Height="350" Width="448">
<Grid.RowDefinitions >
<RowDefinition Height="300" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<ListView ItemsSource="{Binding ImportedJobDataColumns}" Margin="37,68,295,64" local:DragDropHelper.IsDragSource="true">
<ListView.View >
<GridView AllowsColumnReorder="True" >
<GridViewColumn Width="100" Header="Imported"/>
</GridView>
</ListView.View>
</ListView>
<ListView ItemsSource="{Binding KneJobDataColumns}" Margin="193,68,41,64" AllowDrop="True" local:DragDropHelper.IsDropTarget="true">
<ListView.View >
<GridView AllowsColumnReorder="True" >
<GridViewColumn Width="100" Header="Import From" DisplayMemberBinding="{Binding ImportField }" />
<GridViewColumn Width="100" Header="Map To" DisplayMemberBinding="{Binding KneField }" />
</GridView>
</ListView.View>
</ListView>
<Button Content="Open Csv" Height="23" HorizontalAlignment="Left" Margin="37,15,0,0" Name="Button1" VerticalAlignment="Top" Width="75" Command="{Binding OpenCsvCommand}" Grid.Row="1" />
<Button Content="Clean Data" Height="23" HorizontalAlignment="Left" Margin="118,15,0,0" Name="Button2" VerticalAlignment="Top" Width="auto" Grid.Row="1" />
<Button Content="View Imported Data" Height="23" HorizontalAlignment="Left" Margin="193,15,0,0" Name="Button3" VerticalAlignment="Top" Width="auto" Grid.Row="1" />
</Grid>
这看起来很接近我希望看起来如何,但我不能拖拉工作。您可能已经注意到,我正在使用Bea Stollnitz解决方案来尝试实现拖放。 http://bea.stollnitz.com/blog/?p=53她的解决方案只能与ItemsControls一起使用,因此,我担心它不能在我用来创建两列的GridView中工作。我只使用了Listbox来尝试它,拖放功能确实有效但我真的需要两列才能使它工作。
是否有人建议如何在此方案中实施拖放,或者替代我目前正在尝试实现此方法的方式。
非常感谢!
答案 0 :(得分:1)
我最终使用DataGrid而不是ListView,主要是因为它有更多我想要的外观。因为时间有点紧迫,因为我已经浪费了很多时间来解决这个问题,所以我决定在代码隐藏中实现拖放功能。通过阅读这个来改变我对此的看法...... http://forums.silverlight.net/t/225274.aspx/1
虽然我正在处理的情况略有不同,但现在它在代码隐藏中,有一天我或许会将它移到View-Model中以获取新的东西......如果有人不同意,我希望提供一个简单的解决方案,将其移入虚拟机,成为我的客人:)下面是UI图像,显示我正在尝试完成的任务,然后是xaml,然后是代码隐藏。我从http://www.wpftutorial.net/DragAndDrop.html开始,并从那个基础开始工作。这个功能非常特定于这个用户控件,所以虽然我对通过MVVM模式传递鼠标事件的一般概念感兴趣,但我不确定将它应用于这个案例是多么有用。
思想?
<Border BorderBrush="Silver" BorderThickness="1" Grid.RowSpan="2" HorizontalAlignment="Left" Margin="5" Name="Border1" VerticalAlignment="Top" Width="Auto" Height="Auto" >
<StackPanel >
<Expander Header="Instructions" IsExpanded ="False" ExpandDirection="Down" Width="Auto" Height="Auto" >
<TextBlock Text="{Binding Instructions}" TextWrapping="Wrap" Margin="5" />
</Expander>
<Grid Height="420" Width="485">
<Grid.RowDefinitions >
<RowDefinition Height="5*" />
<RowDefinition Height="5*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="6*" />
</Grid.ColumnDefinitions>
<DataGrid AutoGenerateColumns="False" HorizontalAlignment="Stretch"
Margin="5" Name="DataGrid1" VerticalAlignment="Stretch" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2"
ItemsSource="{Binding ImportedJobDataColumns}" SelectionUnit="Cell" CanUserReorderColumns="False"
PreviewMouseLeftButtonDown="DataGrid_MouseLeftButtonDown" MouseMove="DataGrid_MouseMove">
<DataGrid.Columns>
<DataGridTextColumn Header="Imported" Binding="{Binding Path=.}" Width="*" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
<DataGrid AutoGenerateColumns="False" HorizontalAlignment="Stretch"
Margin="5" Name="DataGrid2" VerticalAlignment="Stretch" Grid.Column="1" Grid.Row="0"
ItemsSource="{Binding KneJobDataColumns}" SelectionUnit="Cell" CanUserReorderColumns="False" AllowDrop="True"
PreviewDragOver="DataGrid_PreviewDragOver" Drop="DataGrid_Drop">
<DataGrid.Columns>
<DataGridTextColumn Header="From" Binding="{Binding Path=ImportField}" Width="*"
CanUserReorder="False" CanUserSort="False" IsReadOnly="True"/>
<DataGridTextColumn Header="To" Binding="{Binding KneField}" Width="*"
CanUserSort="False" CanUserReorder="False" IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>
<Grid Margin="5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Column="1" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Content="Auto Map" Grid.Column="0" Name="Button4" Height="Auto" HorizontalAlignment="Stretch" Command="{Binding AutoMap}" />
<Button Content="Clear Map" Grid.Column="1" Name="Button5" Height="Auto" HorizontalAlignment="Stretch" Command="{Binding ClearMappings}"/>
<DockPanel Grid.Row="1" Grid.Column="0" >
<Label Content="Max Press." HorizontalAlignment="Left" Name="Label1" VerticalAlignment="Top" Width="Auto" />
<xctk:IntegerUpDown Value="{Binding MaxPressureInc}" Minimum="1" Increment="10"/>
</DockPanel>
<DockPanel Grid.Row="1" Grid.Column="1" >
<Label Content="Min Depth" Grid.Row="1" Grid.Column="1" Height="28" HorizontalAlignment="Left" Name="Label2" VerticalAlignment="Top" Width="69" />
<xctk:IntegerUpDown Grid.Row="1" Grid.Column="1" Value="{Binding MinDepthInc}" Minimum="1" Increment="1"/>
</DockPanel>
<Button Content="Open Csv" Grid.Row="2" Grid.Column="0" Height="Auto" Name="Button1" Command="{Binding OpenCsv}" />
<Button Content="Clean Data" Grid.Row="2" Grid.Column="1" Height="Auto" Name="Button2" Command="{Binding CleanData}" />
<Button Content="View Imported Data" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Name="Button3" />
<ProgressBar HorizontalAlignment="Stretch" Name="ProgressBar1" VerticalAlignment="Stretch" Grid.Row="4" IsIndeterminate="{Binding IsBusy}"
Foreground="Blue" Background="LightGray" Visibility="{Binding IsBusy, Converter={local:BooleanToVisibilityConverter}}" Grid.ColumnSpan="2" />
<Label Content="Current File:" Grid.Column="0" Grid.Row="5" HorizontalAlignment="Left" VerticalAlignment="Center" />
<TextBlock TextWrapping="Wrap" Text="{Binding CsvFileNameCurrent}" HorizontalAlignment="Right" Name="TextBlock1"
VerticalAlignment="Center" Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Width="Auto" />
</Grid>
</Grid>
</StackPanel>
</Border>
Public Class ImportJobDataView
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.DataContext = New ImportJobDataViewModel
End Sub
Private startPoint As Point
Private Sub DataGrid_MouseLeftButtonDown(sender As System.Object, e As System.Windows.Input.MouseButtonEventArgs)
startPoint = e.GetPosition(Nothing)
End Sub
Private Sub DataGrid_MouseMove(sender As System.Object, e As System.Windows.Input.MouseEventArgs)
'Current Mouse Position
Dim MousePos = e.GetPosition(Nothing)
Dim MouseVector As Vector = startPoint - MousePos
'Only do the following if the left moust button is held, and the cursor has moved more than the minimum horizontal distance
If (e.LeftButton = MouseButtonState.Pressed) And (MouseVector.Length > SystemParameters.MinimumHorizontalDragDistance) Then
If TypeOf e.OriginalSource Is TextBlock Then
'Get the TextBlock inside the Cell
Dim TxtBlock As TextBlock = FindAncestor(Of TextBlock)(DirectCast(e.OriginalSource, FrameworkElement))
'Initialize the drag & drop
Dim DragData As New DataObject("String", TxtBlock.Text)
DragDrop.DoDragDrop(TxtBlock, DragData, DragDropEffects.Copy)
End If
End If
End Sub
Private Sub DataGrid_PreviewDragOver(sender As System.Object, e As System.Windows.DragEventArgs)
If TypeOf e.OriginalSource Is TextBlock Then
Dim Cell As DataGridCell = FindAncestor(Of DataGridCell)(DirectCast(e.OriginalSource, DependencyObject))
'We aren't in a cell, don't allow a drop
If Cell Is Nothing Then
e.Effects = DragDropEffects.None
Exit Sub
End If
'Make sure we don't have a drop in the second column
If (Cell.Column.DisplayIndex > 0) Then
e.Effects = DragDropEffects.None
Else
e.Effects = DragDropEffects.Copy
End If
Else
e.Effects = DragDropEffects.None
End If
End Sub
Private Sub DataGrid_Drop(sender As System.Object, e As System.Windows.DragEventArgs)
If e.Data.GetDataPresent("String") Then
Dim SourceString As String = CStr(e.Data.GetData("String"))
If TypeOf e.OriginalSource Is TextBlock Then
'Write to cell contents only, so that we don't end up writing to the textblock inside the cells header row.
Dim Cell As DataGridCell = FindAncestor(Of DataGridCell)(DirectCast(e.OriginalSource, DependencyObject))
If Cell Is Nothing Then Exit Sub
Cell.Content = SourceString
End If
End If
End Sub
Private Function FindAncestor(Of T As DependencyObject)(current As DependencyObject) As T
Do
If TypeOf current Is T Then
Return DirectCast(current, T)
End If
current = VisualTreeHelper.GetParent(current)
Loop While current IsNot Nothing
Return Nothing
End Function
End Class
答案 1 :(得分:0)
在没有看到代码的情况下很难分辨出确切的问题,但是我之前使用过Bea Stollnitz的DragDrop代码,并且知道她的DragDrop类有一些地方可以将源或目标容器转换为{{1 }}或ItemsControl
或甚至可能是ListBox
,只有在结果不为空时才会继续。
您需要更新这些广告以投射为ListBoxItem
(或ListView
)并调整其中的逻辑以说明ListView的VisualTree(我使用Snoop来查看可视树当某事正在运行时)