首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在画布上移动ListBoxItems?

在画布上移动ListBoxItems?
EN

Stack Overflow用户
提问于 2010-08-06 22:58:58
回答 2查看 989关注 0票数 0

我正致力于在画布周围拖动对象,这些对象封装在ListBoxItems中--其效果是创建一个简单的伪桌面。

我有一个带有画布的ListBox作为ItemsPanelTempalte,这样ListBoxItems就可以显示在屏幕上的任何地方:

代码语言:javascript
复制
<ListBox ItemsSource="{Binding Windows}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

我有一个样式来定义ListBoxItems应该如何显示:

代码语言:javascript
复制
<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扩展而来的,它有自己的样式以使其看起来像对话框(标题栏、关闭按钮等)。下面是其中的一部分:

代码语言:javascript
复制
  <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事件:

代码语言:javascript
复制
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;
}

我遇到的麻烦是“左”和“顶”不是定义好的属性,并将它们更新到Canvas.etLeft/SetTop(或GetLeft/GetTop,相应地)不会更新画布上的位置。

我在我放置到ListBoxItems中的控件的ListBoxItems中定义了“左”和“顶”,因此,由于模板的存在,随后使用了PseudoWindowContainer包装。这些值将被授予,并且当应用程序最初出现时,对象确实会出现在正确的位置上。

我认为我需要在我的PseudoWindowContainer (又名: ContentControl)中定义“左”和“顶”,并让它们传回我的ViewModel。这个是可能的吗?

再次感谢您的帮助!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-08-09 18:12:30

我找到了解决这个问题的办法。与其再次键入所有内容,我将指向描述我所做的事情的MSDN文章:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/d9036b30-bc6e-490e-8f1e-763028a50153

票数 1
EN

Stack Overflow用户

发布于 2010-08-07 01:39:42

你读过Bea:WPF中样式和模板的威力的文章吗?

这是Listbox的一个示例,其中项是在转换器中计算的特定坐标处绘制的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3428370

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档