单击wpf中的列表框usercontrol项

时间:2016-01-07 02:53:47

标签: c# wpf xaml listbox

所以在我的应用程序中,我必须使用类对象类型, Circles Rectangles 。两者都使用ListBox绘制。矩形为绿色,圆圈为黄色。

您可能会问为什么我使用列表框来显示它们。这里的好处是免费赠送用户可以在窗口中点击时选择项目。

我需要帮助的问题,它们都与点击/选择相同的主题有关。

更新时间:2016年1月7日

  1. 由于所有列表框项目都显示为 Box Shaped 命中测试区域,因此会出现类似问题。用户想要选择矩形,但他们会改为使用黄色圆圈。
  2. 问题(左)|期望的目标(右)

    actual

    1. 这导致了我的最后一个问题,即黄圈形状的命中测试。当用户点击否定区域时,它实际上不应该选择该行。它应该只在用户光标直接位于其上时选择该行。如右图所示。理想的是,当它被选中时,高光指示更适合突出显示的形状,而不是一个巨大的矩形。
    2. enter image description here

      就代码而言,它相当短,并且我将它简化为较小的文件。

      MainWindow.xaml

      using System;
      using System.Collections.Generic;
      using System.Collections.ObjectModel;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace WpfApplication1
      {
          public class MainWindowViewModel
          {
      
              private ObservableCollection<ItemViewModel> items = new ObservableCollection<ItemViewModel>();
              public ObservableCollection<ItemViewModel> Items { get { return items; } }
      
              public MainWindowViewModel()
              {
                  // Populate the view model with some example data.
                  items.Add(new RectangleViewModel(250, 200));
                  items.Add(new RectangleViewModel(320, 370));
                  items.Add(new RectangleViewModel(100, 50));
                  items.Add(new RectangleViewModel(350, 25));
                  items.Add(new RectangleViewModel(70, 270));
      
                  items.Add(new CircleViewModel(20, 20));
                  items.Add(new CircleViewModel(300, 270));
                  items.Add(new CircleViewModel(350, 100));
                  items.Add(new CircleViewModel(50, 315));
                  items.Add(new CircleViewModel(100, 170));
              }
          }
      
          public class ItemViewModel
          {
              // position coordinates
              public double X { get; set; }
              public double Y { get; set; }
          }
      
          public class CircleViewModel : ItemViewModel
          {
              // Constructors
              public CircleViewModel(double x, double y)
              {
                  this.X = x;
                  this.Y = y;
              }
          }
          public class RectangleViewModel : ItemViewModel
          {
              // Constructors
              public RectangleViewModel(double x, double y)
              {
                  this.X = x;
                  this.Y = y;
              }
          }
      }
      

      MainWindowViewModel.cs

         using System;
          using System.Collections.Generic;
          using System.Diagnostics;
          using System.Linq;
          using System.Text;
          using System.Windows;
          using System.Windows.Controls;
          using System.Windows.Data;
          using System.Windows.Documents;
          using System.Windows.Input;
          using System.Windows.Media;
          using System.Windows.Media.Imaging;
          using System.Windows.Navigation;
          using System.Windows.Shapes;
      
          namespace DragShapes
          {
              /// <summary>
              /// Interaction logic for MainWindow.xaml
              /// </summary>
              public partial class MainWindow : Window
              {
                  public MainWindow()
                  {
                      InitializeComponent();
                  }
      
                  bool captured = false;
                  double x_shape, x_canvas, y_shape, y_canvas;
                  UIElement source = null;
      
                  private void shape_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
                  {
                      Console.WriteLine("MouseDown--Pressed");
                      source = (UIElement)sender;
                      Mouse.Capture(source);
                      captured = true;
                      x_shape = Canvas.GetLeft(source);
                      x_canvas = e.GetPosition(LayoutRoot).X;
                      y_shape = Canvas.GetTop(source);
                      y_canvas = e.GetPosition(LayoutRoot).Y;
                  }
      
                  private void shape_MouseMove(object sender, MouseEventArgs e)
                  {
                      if (captured)
                      {
                          Console.WriteLine("MouseMove--Pressed");
                          double x = e.GetPosition(LayoutRoot).X;
                          double y = e.GetPosition(LayoutRoot).Y;
                          x_shape += x - x_canvas;
                          Canvas.SetLeft(source, x_shape);
                          x_canvas = x;
                          y_shape += y - y_canvas;
                          Canvas.SetTop(source, y_shape);
                          y_canvas = y;
                      }
                  }
      
                  private void 
      
      shape_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
              {
                  Console.WriteLine("MouseUp--Pressed");
                  Mouse.Capture(null);
                  captured = false;
              }
          }
      }
      

      更新 - 更接近 - 尝试#2

      enter image description here

      现在我可以在画布中拖动和移动项目,点击的hitTest是正确的。但是出于某些原因,当我尝试在底部蓝色画布中移动形状时,它们不会移动,而它们会在顶部移动。试试吧......

      MainWindow.xaml.cs

        using System;
          using System.Collections.Generic;
          using System.Collections.ObjectModel;
          using System.ComponentModel;
          using System.Linq;
          using System.Text;
          using System.Threading.Tasks;
      
      
          namespace DragShapes
          {
              public class MainWindowViewModel
              {
      
                  private ObservableCollection<ItemViewModel> items = new ObservableCollection<ItemViewModel>();
                  public ObservableCollection<ItemViewModel> Items { get { return items; } }
      
                  public MainWindowViewModel()
                  {
                      // Populate the view model with some example data.
                      items.Add(new RectangleViewModel(250, 200));
                      items.Add(new RectangleViewModel(320, 370));
                      items.Add(new RectangleViewModel(100, 50));
                      items.Add(new RectangleViewModel(350, 25));
                      items.Add(new RectangleViewModel(70, 270));
      
                      items.Add(new CircleViewModel(20, 20));
                      items.Add(new CircleViewModel(300, 270));
                      items.Add(new CircleViewModel(350, 100));
                      items.Add(new CircleViewModel(50, 315));
                      items.Add(new CircleViewModel(100, 170));
                  }
              }
      
              public class ItemViewModel : INotifyPropertyChanged
              {
                  // position coordinates
                  private double x = 0;
                  public double X
                  {
                      get { return x; }
                      set
                      {
                          if (x != value)
                          {
                              x = value;
                              OnPropertyChanged("X");
                          }
                      }
                  }
      
                  private double y = 0;
                  public double Y
                  {
                      get { return y; }
                      set
                      {
                          if (y != value)
                          {
                              y = value;
                              OnPropertyChanged("Y");
                          }
                      }
                  }
      
                  protected void OnPropertyChanged(string name)
                  {
                      if (PropertyChanged != null)
                      {
                          PropertyChanged(this, new PropertyChangedEventArgs(name));
                      }
                  }
                  public event PropertyChangedEventHandler PropertyChanged;
              }
      
              public class CircleViewModel : ItemViewModel
              {
                  // Constructors
                  public CircleViewModel(double x, double y)
                  {
                      this.X = x;
                      this.Y = y;
                  }
              }
              public class RectangleViewModel : ItemViewModel
              {
                  // Constructors
                  public RectangleViewModel(double x, double y)
                  {
                      this.X = x;
                      this.Y = y;
                  }
              }
      
      
          }
      

      MainWindowViewModel.cs

      <Window x:Class="DragShapes.MainWindow"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              Title="MainWindow" Height="600" Width="600"
              xmlns:local="clr-namespace:DragShapes">
      
          <Window.DataContext>
              <local:MainWindowViewModel />
          </Window.DataContext>
      
          <Window.Resources>
      
              <DataTemplate DataType="{x:Type local:RectangleViewModel}" >
                  <Rectangle Cursor="Hand" Fill="Green" Width="100" Height="100" Margin="10"
                          MouseLeftButtonDown="shape_MouseLeftButtonDown" 
                          MouseMove="shape_MouseMove" 
                          MouseLeftButtonUp="shape_MouseLeftButtonUp"/>
              </DataTemplate>
      
              <DataTemplate DataType="{x:Type local:CircleViewModel}" >
                  <Path Data="M0,0 C0,0  10,100  100,100" Stroke="Gold" StrokeThickness="5" Cursor="Hand"
                        MouseLeftButtonDown="shape_MouseLeftButtonDown" 
                        MouseLeftButtonUp="shape_MouseLeftButtonUp"
                        MouseMove="shape_MouseMove"/>
              </DataTemplate>
      
          </Window.Resources>
      
          <Grid>
              <Grid.RowDefinitions>
                  <RowDefinition Height="*"/>
                  <RowDefinition Height="*"/>
              </Grid.RowDefinitions>
      
              <Canvas x:Name="LayoutRoot" Background="White">
      
                  <Ellipse Fill="Blue" HorizontalAlignment="Center" Height="100" Stroke="Black" VerticalAlignment="Center" Width="100" Canvas.Left="200" Canvas.Top="100"
                           MouseLeftButtonDown="shape_MouseLeftButtonDown" 
                           MouseMove="shape_MouseMove" 
                           MouseLeftButtonUp="shape_MouseLeftButtonUp" />
      
                  <Rectangle Fill="Red" Height="100" Stroke="Black" Width="100" HorizontalAlignment="Left" VerticalAlignment="Bottom" Canvas.Left="10" Canvas.Top="10" 
                             MouseLeftButtonDown="shape_MouseLeftButtonDown" 
                             MouseLeftButtonUp="shape_MouseLeftButtonUp"
                             MouseMove="shape_MouseMove"/>
      
              </Canvas>
      
              <Canvas Grid.Row="1"  Background="White" >
      
                  <ItemsControl ItemsSource="{Binding Path=Items}" >
      
                      <ItemsControl.ItemsPanel>
                          <ItemsPanelTemplate>
                              <Canvas Background="LightBlue" Width="500" Height="500"  />
                          </ItemsPanelTemplate>
                      </ItemsControl.ItemsPanel>
      
                      <!--<ItemsControl.ItemTemplate>
                          <DataTemplate>
                              <Ellipse Fill="Green" Width="25" Height="25" 
                                       MouseLeftButtonDown="shape_MouseLeftButtonDown" 
                                       MouseLeftButtonUp="shape_MouseLeftButtonUp"
                                       MouseMove="shape_MouseMove"/>
                          </DataTemplate>
                      </ItemsControl.ItemTemplate>-->
      
                      <ItemsControl.ItemContainerStyle>
                          <Style>
                              <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
                              <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
                          </Style>
                      </ItemsControl.ItemContainerStyle>
                  </ItemsControl>
      
                  <!--<ItemsControl ItemsSource="{Binding Path=Items}">
                      <ItemsControl.ItemsPanel>
                          <ItemsPanelTemplate>
                              <Canvas/>
                          </ItemsPanelTemplate>
                      </ItemsControl.ItemsPanel>
                      <ItemsControl.ItemContainerStyle>
                          <Style TargetType="ContentPresenter">
                              <Setter Property="Canvas.Left" Value="{Binding X}"/>
                              <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                          </Style>
                      </ItemsControl.ItemContainerStyle>
                  </ItemsControl>-->
      
                  <!--<ItemsControl ItemsSource="{Binding Path=Items}">
                      --><!--<ItemsControl.ItemContainerStyle>
                          <Style TargetType="ContentPresenter">
                              <Setter Property="Canvas.Left" Value="{Binding X}"/>
                              <Setter Property="Canvas.Top" Value="{Binding Y}"/>
                          </Style>
                      </ItemsControl.ItemContainerStyle>--><!--
                  </ItemsControl>-->
              </Canvas>
          </Grid>
      </Window>
      

      MainWindow.xaml

      {{1}}

1 个答案:

答案 0 :(得分:2)

默认的ListBoxItem模板具有活动背景,因此我们需要重置模板,如下所示:

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem" >
        <Setter Property="Canvas.Left" Value="{Binding X}" />
        <Setter Property="Canvas.Top" Value="{Binding Y}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <ContentPresenter/>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" Value="LightBlue"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ListBox.ItemContainerStyle>

然后,我们需要修改矩形和圆形模板,以便在选择它们时获得选择效果:

<DataTemplate DataType="{x:Type local:RectangleViewModel}" >
    <Grid>
        <Border CornerRadius="4"
                Background="{Binding 
                    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, 
                    Path=Background}"/>
        <Border Cursor="Hand" Background="Green" CornerRadius="4" Width="100" Height="100" Margin="10"/>
    </Grid>
</DataTemplate>

<DataTemplate DataType="{x:Type local:CircleViewModel}" >
    <Grid>
        <Path Data="M0,0 C0,0  10,100  100,100" StrokeThickness="15"
              Stroke="{Binding 
                RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, 
                Path=Background}"/>
        <Path Data="M0,0 C0,0  10,100  100,100" Stroke="Gold" StrokeThickness="5" Cursor="Hand"/>
    </Grid>
</DataTemplate>
相关问题