C#WPF Drag&删除ListBox MVVM

时间:2011-04-12 08:44:02

标签: c# wpf mvvm drag-and-drop listbox

我想在我的应用程序中启用拖放功能,以便能够在组件之间创建连接。这听起来不太难,但问题是我想要连接的组件类型。

我希望能够建立联系的原因是能够制作图表并计算最短路径等。

我所拥有的是一个ListBox,其中包含放置在Canvas上的Components。我使用ListBox的原因是使组件可选。我也把它们弄得一团糟。

<DataTemplate DataType="{x:Type ViewModels:DocumentViewModel}">
    <DataTemplate.Resources>
        <Converters:GuiSizeConverter x:Key="SizeConverter"/>
    </DataTemplate.Resources>
    <ListBox ItemsSource="{Binding Components}" SelectedItem="{Binding SelectedItem}" Background="Transparent" 
             HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="0" Margin="0">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas ClipToBounds="True" Height="{Binding CurrentProject.Height, Converter={StaticResource SizeConverter}}"
                        Width="{Binding CurrentProject.Width, Converter={StaticResource SizeConverter}}">
                    <Canvas.Background>
                        <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.WindowFrameColorKey}}"/>
                    </Canvas.Background>
                </Canvas>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="HorizontalAlignment" Value="Stretch" />
                <Setter Property="Background" Value="Transparent" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBoxItem}">
                            <Grid>
                                <Border Background="{TemplateBinding Background}" />
                                <ContentPresenter/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsMouseOver" Value="True" />
                                        <Condition Property="IsSelected" Value="False"/>
                                    </MultiTrigger.Conditions>
                                    <Setter Property="Background" Value="#8868D5FD" />
                                </MultiTrigger>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="Background" Value="#4468D5FD" />
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Setter Property="Utils:DraggableExtender.CanDrag" Value="True" />
                <Setter Property="Canvas.Top" Value="{Binding Path=Y, Converter={StaticResource SizeConverter},Mode=TwoWay}" />
                <Setter Property="Canvas.Left" Value="{Binding Path=X, Converter={StaticResource SizeConverter},Mode=TwoWay}" />
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>
</DataTemplate>

现在最棘手的事情是它不是我的ViewModel中的组件我想使用拖放,而是这些组件中的组件。为了更好地说明这一点,请参阅火车站的示例图片和下面的曲目。我有PlaceableComponents(列表框中的那些),即Track和Station。轨道由TrackSections构成,可以是常规轨道部分和电气轨道部分。 Station是由Platforms构建的,它由TrackSections构建的Tracks构建。

canvas in action

所以我要连接的组件(或节点)是TrackSections,所以我想将一个部分拖放(使用鼠标右键)到另一个部分,这应该在我的DocumentViewModel中调用一个方法(命令)(在画布上保存项目的viewmodel而不是在部分上,因为这些部分没有关于其他组件的线索,也不应该保持连接。

目标是创建一个连接列表(包含from和to components),这些连接应该可以使用装饰层或类似方法在线条上呈现为线条。我还可以补充说,可用于创建连接的组件都实现了一个INode接口,以便能够识别它们。

我希望我能够清楚地描述我的问题和情况。我可以补充一点,我发现了很多关于拖拉的好帖子。但是我无法将其中任何一个应用到我的案例中,这就是我在这里问的原因。

1 个答案:

答案 0 :(得分:0)

是否要首先在画布上放置组件,然后通过从一个组件拖动到另一个组件来创建它们之间的连接?现在你的问题是什么?下降?为什么您认为组件的类型是个问题?

我只能猜出你真正想要的东西,但也许下面的方法可能有效:

  • 右键单击,确定鼠标悬停的组件和轨迹部分
  • 在拖动中确定您是否正在悬停另一个允许丢弃的组件(提供视觉提示)
  • 如果允许丢弃,请检查您正在悬停的轨迹部分
  • 创建tracksections的连接

以下是指向Drag&Drop-Framework的链接。