WPF - 用图钉标记图像

时间:2015-12-14 12:37:44

标签: c# wpf image xaml maps

enter image description here

  • 我需要在WPF应用程序中显示图像(固定大小)。
  • 应该能够用引脚标记图像,如上所示 图像。
  • 它应该能够为每个引脚添加描述,并在悬停时 在引脚上应该显示描述。
  • 最后我需要保存SQL数据库中的所有信息才能显示 再次引脚。

通过创建自定义控件可以实现这一目标吗? 请建议您实施此解决方案的想法。 提供示例将受到高度赞赏。

1 个答案:

答案 0 :(得分:2)

回答你的问题:是的,这是可能的。

在使用WPF时,我强烈推荐MVVM架构模式。你需要的是:

  1. canvas控制以使用绝对定位
  2. 将显示背景图片的image控件
  3. 自定义引脚控件,用于显示引脚图像。此控件还可以包含将用于生成描述控件的DataTemplate。
  4. 一个自定义控件,将显示有关该引脚的信息(将在弹出窗口中使用)
  5. adorner将在装饰图层中呈现引脚信息弹出窗口。将装饰器装饰器放在与画布相同的位置。
  6. 您需要存储的关于pin的信息:

    1. 其Canvas.Top和Canvas.Left值
    2. 影响其视觉特性的属性(例如图像,颜色等)
    3. 弹出窗口中显示的信息(例如说明,图片)
    4. 然后,您可以读取数据库中的所有条目,并为每个条目创建引脚视图模型,并将视图模型绑定到画布中的项控件。不要忘记将引脚控件的属性绑定到其视图模型的相应值(例如Canvas.Left,Canvas.Top,Description etc)。

      对于弹出窗口,一旦您创建了您的adorner类,当您需要显示弹出窗口时将其添加到画布的adorner层,并在需要关闭弹出窗口时将其删除。

      下面可以看到地图控件样式的一个示例(假设地图控件的视图模型包含一个可观察的引脚集合):

      <Style TargetType="{x:Type local:Map}">
          <Setter Property="Template">
              <Setter.Value>
                  <ControlTemplate TargetType="{x:Type local:Map}">
                      <Border Background="{TemplateBinding Background}"
                              BorderBrush="{TemplateBinding BorderBrush}"
                              BorderThickness="{TemplateBinding BorderThickness}">
      
                          <Grid>
                              <AdornerDecorator></AdornerDecorator>
      
                              <ItemsControl ItemsSource="{Binding Path=Items}">
                                  <ItemsControl.ItemsPanel>
                                      <ItemsPanelTemplate>
                                          <Canvas Background="White">
      
                                          </Canvas>
                                      </ItemsPanelTemplate>
                                  </ItemsControl.ItemsPanel>
                                  <ItemsControl.ItemTemplate>
                                      <DataTemplate>
                                          <local:Pin></local:Pin>
                                      </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>
                          </Grid>
                      </Border>
                  </ControlTemplate>
              </Setter.Value>
          </Setter>
      </Style>
      

      这是一个简单渲染给定FrameworkElement的adorner控件示例:

      public class ControlAdorner : Adorner {
      
          FrameworkElement _control;
          public FrameworkElement Control {
              get {
                  return (_control);
              }
              set {
                  _control = value;
              }
          }
      
          public ControlAdorner(UIElement Element, FrameworkElement Control)
              : base(Element) {
              this.Control = Control;
              this.AddVisualChild(this.Control);
              this.IsHitTestVisible = false;
          }
      
          protected override Visual GetVisualChild(int index) {
              if (index != 0) throw new ArgumentOutOfRangeException();
              return _control;
          }
      
          protected override int VisualChildrenCount {
              get {
                  return 1;
              }
          }
      
          public void UpdatePosition(Point point) {
              VisualOffset = new Vector(point.X, point.Y);
              this.InvalidateVisual();
          }
      
          protected override Size MeasureOverride(Size constraint) {
              Control.Measure(constraint);
              return Control.DesiredSize;
          }
      
          protected override Size ArrangeOverride(Size finalSize) {
              Control.Arrange(new Rect(new Point(VisualOffset.X, VisualOffset.Y - 20), finalSize));
              return new Size(Control.ActualWidth, Control.ActualHeight);
          }
      }
      

      以下是鼠标悬停时如何让Pin控件显示装饰器:

      public class Pin : Control {
          public DataTemplate DescriptionItemTemplate {
              get { return (DataTemplate)GetValue(DescriptionItemTemplateProperty); }
              set { SetValue(DescriptionItemTemplateProperty, value); }
          }
          public static readonly DependencyProperty DescriptionItemTemplateProperty =
              DependencyProperty.Register("DescriptionItemTemplate", typeof(DataTemplate), typeof(Pin), new PropertyMetadata(null));
      
      
      
      
          ControlAdorner _adorner;
          AdornerLayer _adornerLayer;
      
          static Pin() {
              DefaultStyleKeyProperty.OverrideMetadata(typeof(Pin), new FrameworkPropertyMetadata(typeof(Pin)));
          }
      
          public Pin() {
              this.MouseEnter += Pin_MouseEnter;
              this.MouseLeave += Pin_MouseLeave;
          }
      
          private void Pin_MouseEnter(object sender, MouseEventArgs e) {
              _adornerLayer = AdornerLayer.GetAdornerLayer(this);
      
              FrameworkElement element = DescriptionItemTemplate.LoadContent() as FrameworkElement;
              if (element == null) { return; }
              element.DataContext = this.DataContext;
      
              _adorner = new ControlAdorner(this, element);
              _adornerLayer.Add(_adorner);
          }
      
      
          private void Pin_MouseLeave(object sender, MouseEventArgs e) {
              _adornerLayer.Remove(_adorner);
              _adorner = null;
          }
      }