在画布上移动 ListBoxItems? [英] Moving ListBoxItems around a Canvas?

查看:40
本文介绍了在画布上移动 ListBoxItems?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在围绕 Canvas 拖动对象,这些对象封装在 ListBoxItems 中 -- 其效果是创建一个简单的伪桌面.

I'm working on dragging objects around a Canvas, which are encapsulated in ListBoxItems -- the effect being to create a simple pseudo desktop.

我有一个带有 Canvas 作为 ItemsPanelTempalte 的 ListBox,因此 ListBoxItems 可以出现在屏幕上的任何位置:

I have a ListBox with a Canvas as the ItemsPanelTempalte, so that the ListBoxItems can appear anywhere on screen:

<ListBox ItemsSource="{Binding Windows}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

我有一个样式来定义 ListBoxItems 的显示方式:

I have a Style to define how the ListBoxItems should appear:

<Style TargetType="{x:Type ListBoxItem}">
    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
    <Setter Property="Canvas.Left" Value="{Binding Left, Mode=TwoWay}" />
    <Setter Property="Canvas.Top" Value="{Binding Top, Mode=TwoWay}" />
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                <local:PseudoWindowContainer Content="{TemplateBinding Content}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

PseudoWindowContainer"从 ContentControl 扩展而来,并应用了自己的样式,使其看起来像一个对话框(标题栏、关闭按钮等...).这是其中的一部分:

The "PseudoWindowContainer" extends from the ContentControl and has its own Style applied to make it look like a dialog box (title bar, close button, etc...). Here is a chunk of it:

  <Style TargetType="{x:Type local:PseudoWindowContainer}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="Width" Value="{Binding Width, Mode=TwoWay}" />
<Setter Property="Height" Value="{Binding Height, Mode=TwoWay}" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
  <Setter.Value>
    <ControlTemplate TargetType="{x:Type local:PseudoWindowContainer}">
      <Grid Name="LayoutRoot" Background="White">
        <!-- ... snip ... -->
            <Border Name="PART_TitleBar" Grid.Row="0" Background="LightGray" CornerRadius="2,2,0,0" VerticalAlignment="Stretch" Cursor="Hand" />
            <TextBlock Name="TitleBar_Caption" Text="{Binding DisplayName}" Grid.Row="0" Background="Transparent" Padding="5,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" />
            <Button Name="TitleBar_CloseButton" Command="{Binding CloseCommand}" Grid.Row="0" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,5,5,0" Width="20" Height="20" Cursor="Hand" Background="#FFFF0000" Foreground="#FF212121" />
            <!-- ContentPresenter -->
            <ContentPresenter Grid.Row="1" />
        <!-- ... snip ... -->
      </Grid>
      <ControlTemplate.Triggers>
        <Trigger Property="IsSelected" Value="True">
          <Setter TargetName="WindowBorder" Property="Background" Value="Blue" />
        </Trigger>
        <Trigger Property="IsSelected" Value="False">
          <Setter TargetName="WindowBorder" Property="Background" Value="#22000000" />
        </Trigger>
      </ControlTemplate.Triggers>
    </ControlTemplate>
  </Setter.Value>
</Setter>

在 PseudoWindowContainer.cs 类中,我创建了一些事件处理程序来监听 MouseDown/MouseUp/MoveMove 事件:

Inside the PseudoWindowContainer.cs class I create some event handlers to listen for MouseDown/MouseUp/MoveMove events:

public override void OnApplyTemplate()
{
  _titleBar = (Border)Template.FindName("PART_TitleBar", this);
  if (_titleBar != null)
  {
    _titleBar.MouseDown += TitleBar_MouseDown;
    _titleBar.MouseUp += TitleBar_MouseUp;
  }

  _grip = (ResizeGrip)Template.FindName("PART_ResizeGrip", this);
  if (_grip != null)
  {
    _grip.MouseLeftButtonDown += ResizeGrip_MouseLeftButtonDown;
    _grip.MouseLeftButtonUp += ResizeGrip_MouseLeftButtonUp;
  }

  base.OnApplyTemplate();
}

private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
{
  _titleBar.MouseMove += TitleBar_MouseMove;
  ((Border)sender).CaptureMouse();

  _windowLocation.X = Left;
  _windowLocation.Y = Top;

  _clickLocation = this.PointToScreen(Mouse.GetPosition(this));
}

private void TitleBar_MouseUp(object sender, MouseButtonEventArgs e)
{
  _titleBar.MouseMove -= TitleBar_MouseMove;
  ((Border)sender).ReleaseMouseCapture();
}

private void TitleBar_MouseMove(object sender, MouseEventArgs e)
{
  Point currentLocation = this.PointToScreen(Mouse.GetPosition(this));

  Left = _windowLocation.X + currentLocation.X - _clickLocation.X;
  Top = _windowLocation.Y + currentLocation.Y - _clickLocation.Y;
}

我遇到的问题是Left"和Top"不是定义的属性,将它们更新为 Canvas.SetLeft/SetTop(或 GetLeft/GetTop,相应地)不会更新 Canvas 上的位置.

The trouble I run into is the "Left" and "Top" are not defined properties, and updating them to Canvas.SetLeft/SetTop (or GetLeft/GetTop, accordingly) does not update the position on the Canvas.

我在控件的 ViewModel 中定义了Left"和Top",我将放入 ListBoxItems,因此由于模板的原因,随后用 PseudoWindowContainer 包装.当应用程序最初出现时,这些值得到尊重并且对象确实出现在正确的位置.

I have "Left" and "Top" defined in the ViewModel of the controls I place into the ListBoxItems, and are thus subsequently wrapped with a PseudoWindowContainer because of the Template. These values are being honored and the objects do appear in the correct location when the application comes originally.

我相信我需要以某种方式在我的 PseudoWindowContainer(又名:ContentControl)中定义Left"和Top",并将它们传播回我的 ViewModel.这可能吗?

I believe I need to somehow define "Left" and "Top" in my PseudoWindowContainer (aka: ContentControl) and have them propagate back up to my ViewModel. Is this possible?

再次感谢您的帮助!

推荐答案

我找到了问题的解决方案.我将指向 MSDN 论坛帖子,而不是再次输入所有内容,其中描述了我所做的事情:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/d9036b30-bc6e-490e-8f1e-763028a50153

I've found a solution to the problem. Instead of typing it all out again, I will point to the MSDN Forum post that describes what I did: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/d9036b30-bc6e-490e-8f1e-763028a50153

这篇关于在画布上移动 ListBoxItems?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆