0

こんにちは、アプリケーションを WPF に移行しようとしています。できるだけ MVVM を保持しようとしています。私の WinForm アプリの次の画面はかなり簡単に作成できましたが、Xaml と WPF ではうまくいきませんでした。

WinForm カスタム フィールド マッピングのスクリーン ショット

私はこれがどのように機能するかを気に入っていますが、ここでの私の目標は、これを 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 でのみ機能するように作成されているため、2 つを作成するために使用している GridView 内では機能していないのではないかと心配しています。列。リストボックスだけで試してみましたが、ドラッグ アンド ドロップ機能は機能しますが、これを機能させるには 2 つの列が必要です。

ここに画像の説明を入力

このシナリオでドラッグ アンド ドロップを実装する方法、または現在これを実装しようとしている方法の代替案を誰かが持っていますか。

どうもありがとう!

4

2 に答える 2

1

ListView の代わりに DataGrid を使用することになりました。時間が少し迫っていたので、既にこの問題にかなりの時間を費やしていたため、コード ビハインドにドラッグ アンド ドロップ機能を実装することにしました。これに関する私の意見は、これを読んで変更されました... http://forums.silverlight.net/t/225274.aspx/1

私が取り組んでいる状況は少し異なりますが、今のところコード ビハインドにありますが、いつか新しいことを学ぶためだけにそれをビュー モデルに移動することになるでしょう...誰かが同意しない場合、これを VM に移動するための簡単なソリューションを提示してください。私のゲストになってください :) 以下は、私が達成しようとしていることを示す UI 画像です。その後に xaml と分離コードがあります。http://www.wpftutorial.net/DragAndDrop.htmlから始めて、それに基づいて作業しました。この機能は、まさにこの 1 つのユーザー コントロールに固有のものであるため、MVVM パターンを介してマウス イベントを渡すという一般的な概念に興味がありますが、この 1 つのケースにそれを適用することがどれほど役立つかはわかりません。

考え?

カスタム マップ フィールド

<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
于 2012-07-22T05:05:52.807 に答える
0

コードを見ずに正確な問題が何であるかを判断するのは難しいですが、私は以前に Bea Stollnitz の DragDrop コードを使用したことがあり、彼女の DragDrop クラスには、ソースまたはターゲット コンテナーをItemsControlorListBoxまたは場合によっては, にキャストする場所がいくつかあったことを知っていますListBoxItem。結果が null でない場合にのみ続行されます。

これらのスポットをListView(またはListViewItem) としてキャストするように更新し、ListView の VisualTree を考慮してロジックを調整する必要があります (何かが実行されているときにSnoopを使用して Visual Tree を表示します)。

于 2012-07-13T13:36:18.467 に答える