Canvas ItemsControl中的多个图像

KOT*_*TIX 1 wpf xaml itemscontrol

我想在画布上显示多个图像.我需要在画布中以不同的方式定位它们.我为我的图像上了一堂课:

class MapItem:Image
{
  public int DistanceToTop { get; set; }
  public int DistanceToLeft { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的XAML看起来像这样:

<UserControl.DataContext>
    <Map:MapViewModel/>
</UserControl.DataContext>

<ItemsControl ItemsSource="{Binding All}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="Image">
            <Setter Property="Canvas.Left" Value="{Binding DistanceToLeft}" />
            <Setter Property="Canvas.Top" Value="{Binding DistanceToTop}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

我的ViewModel用作DataContext:

class MapViewModel : ViewModelBase
{
  public ObservableCollection<MapItem> All   { get; set; }

  public MapViewModel()
  {
    All = new ObservableCollection<MapItem>();
    var wSource = new BitmapImage(new Uri(@"ImagePath"));
    var wImage = new MapItem { Source = wSource, DistanceToLeft = 20, DistanceToTop = 20 };
    test = wImage;
    All.Add(wImage);
  }
}
Run Code Online (Sandbox Code Playgroud)

为什么在XAML中我对DistanceToLeft和DistanceToTop的绑定不起作用?!?是不是假设自动查看我的ObservableCollection中的对象使用?

编辑:我还有我的问题.但现在我知道它与Binding有关.我正在尝试使用GalaSoft框架使用MVVM模式实现所有这些.所以开始我将我的DataContext设置为MapViewModel.为什么我不能从ObservableCollection访问MapItem的属性?

编辑:最后在Clemens和Rachel的帮助下,我最终得到了这个.

我的MapItem类:

class MapItem:Image
{
  public LatLon CoordMiddleOfImage { get; set; }
  public LatLon CoordTopLeftOfImage { get; set; }

  public int DistanceToTop
  {
    get { return (int) Canvas.GetTop(this); }
    set { Canvas.SetTop(this, value); }
  }

  public int DistanceToLeft
  {
    get { return (int)Canvas.GetLeft(this); }
    set { Canvas.SetLeft(this, value); }
  }

  public int ZOrder
  {
    get { return Panel.GetZIndex(this); }
    set { Panel.SetZIndex(this, value); }
  }
}
Run Code Online (Sandbox Code Playgroud)

我的XAML是这样的:

<ItemsControl ItemsSource="{Binding All}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas ClipToBounds="True"  SnapsToDevicePixels="True"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

它现在像一个魅力:-)

Cle*_*ens 5

我不太明白为什么你毕竟发明了这些DistanceToLeftDistanceToTop属性然后与绑定斗争.如果要将图像控件用作项目,为什么不直接应用附加属性,Canvas.Left并且Canvas.Top:

All = new ObservableCollection<Image>(); // no need for derived MapItem
var wSource = new BitmapImage(new Uri(@"ImagePath")); 
var wImage = new Image { Source = wSource }; 
Canvas.SetLeft(wImage, 20);
Canvas.SetTop(wImage, 20);
All.Add(wImage); 
Run Code Online (Sandbox Code Playgroud)

因此,不需要风格:

<ItemsControl ItemsSource="{Binding All}">    
    <ItemsControl.ItemsPanel>    
        <ItemsPanelTemplate>    
            <Canvas />    
        </ItemsPanelTemplate>    
    </ItemsControl.ItemsPanel>    
</ItemsControl> 
Run Code Online (Sandbox Code Playgroud)

但是,您应该考虑创建一个不是控件的真实ViewModel类,如下所示:

public class ImageItem
{
    public string Source { get; set; }
    public double Left { get; set; }
    public double Top { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

使用它类似于您的MapItem类

All = new ObservableCollection<ImageItem>();
ImageItem image = new ImageItem { Source = @"ImagePath", Left = 20, Top = 20 };
All.Add(image);
Run Code Online (Sandbox Code Playgroud)

您现在可以像这样定义ItemContainerStyle:

<ItemsControl.ItemContainerStyle>
    <!-- ContentPresenter is the default item container in ItemsControl -->
    <Style TargetType="ContentPresenter">
        <Setter Property="Canvas.Left" Value="{Binding Left}"/>
        <Setter Property="Canvas.Top" Value="{Binding Top}"/>
        <Setter Property="ContentTemplate">                        
            <Setter.Value>
                <DataTemplate>
                    <Image Source="{Binding Source}"/>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ItemsControl.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)