2012-07-11 54 views
0

嗨試圖將我的應用程序遷移到WPF,並且我試圖儘可能多地保留MVVM。從我的WinForm應用程序的以下屏幕相當容易創建,我沒有Xaml和WPF這樣的好運氣。使用ListView的WPF UI從Csv文件映射自定義字段

Screen Shot of WinForm Custom Field mapping

我喜歡它是如何工作的,但我的目標是要麼與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。我已經試過了,只是Listboxes和拖放功能確實工作,但我真的需要兩列才能做到這一點。

enter image description here

有誰要麼就如何落實在這種情況下拖放一個建議,或者我目前想實現這個方式的替代方案。

非常感謝!

回答

1

我結束使用DataGrid而不是ListView,主要是因爲它有更多我想要的外觀。因爲時間有點緊迫,因爲我已經在這個問題上浪費了很多,所以我決定只在代碼隱藏中實現拖放功能。我對此的看法是通過閱讀這個改變的... http://forums.silverlight.net/t/225274.aspx/1

雖然我正在使用的情況稍有不同,現在它在代碼隱藏中,有一天我可能會將它移入View-模型只是爲了學習新東西...如果有人不同意,並且想要提出一個簡單的解決方案將其移入虛擬機,請成爲我的客人:)下面是UI圖像,顯示了我正在嘗試完成的內容,並遵循那就是xaml,然後是代碼隱藏。我從http://www.wpftutorial.net/DragAndDrop.html開始,並從那個基礎開始工作。這個功能對於這個用戶控件來說非常具體,所以雖然我對通過MVVM模式傳遞鼠標事件的一般概念感興趣,但我不確定將它應用於這種情況是多麼有用。

想法?

Custom Mapped Fields

<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 
0

它很難說出確切的問題是什麼,沒有看到代碼,但是我以前跟比Stollnitz的的DragDrop代碼工作,知道她的DragDrop班有幾個地方,她投源或目標容器的ItemsControlListBox或甚至可能是ListBoxItem,並且只在結果不爲空時繼續。

您需要更新這些斑點投作爲一個ListView(或ListViewItem),調整的邏輯在那裏佔ListView的的VisualTree(我用Snoop查看可視化樹的東西正在運行時)

+0

感謝雷切爾,我終於實現了在代碼隱藏的拖放特定的功能,我結束了使用數據網格。我會發布我的代碼和更多細節,因爲它可能會幫助別人,Snoop非常酷! – GetFuzzy 2012-07-21 20:40:36