WPF Canvas Scaling/Transform to Fit

Ian*_*Ian 17 c# wpf canvas scaletransform

我正在重新提出这个问题,因为我上次没有得到太多回应,希望一些重新措辞可能会有所帮助......

基本上我要做的是创建一个数据绑定画布,它将自动缩放其内容以"填充"可用空间.有点像缩放以适应操作.不幸的是,我的WPF技能还不是很强,我正在努力研究如何做到最后这部分.我已经按照一些数据绑定示例来获取画布,但不确定是否可能是错误并阻碍了我.

根据我尝试和解决方案的方式,我现在有两个基本问题:

  • 如果可能使用转换,我不知道如何通过XAML自动重新缩放画布.
  • 我似乎无法在后面的代码中引用画布,我猜是因为它是ItemsControl的一部分?

我想要实现的一个例子,我有AI想要尝试获得B:

(删除过期链接到img)

我目前使用的代码非常简单,只需使用给定的坐标创建4个点,并使用另一个视图模型将其包装起来.

public class PointCollectionViewModel
{
    private List<PointViewModel> viewModels;
    public PointCollectionViewModel()
    {
        this.viewModels = new List<PointViewModel>();
        this.viewModels.Add(new PointViewModel(new Point(1, 1)));
        this.viewModels.Add(new PointViewModel(new Point(9, 9)));
        this.viewModels.Add(new PointViewModel(new Point(1, 9)));
        this.viewModels.Add(new PointViewModel(new Point(9, 1)));
    }

    public List<PointViewModel> Models
    {
        get { return this.viewModels; }
    }
}

public class PointViewModel
{
   private Point point;
   public PointViewModel(Point point)
   {
       this.point = point;
   }

   public Double X { get { return point.X; } }
   public Double Y { get { return point.Y; } }
}
Run Code Online (Sandbox Code Playgroud)

然后将PointCollectionViewModel用作我的AutoResizingCanvas的DataContent,它具有以下XAML来实现绑定:

<UserControl x:Class="WpfCanvasTransform.AutoResizingCanvas"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfCanvasTransform"
    x:Name="parent">
    <ItemsControl x:Name="itemsControl" ItemsSource="{Binding Path=Models}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
        <Canvas x:Name="canvas" Background="DarkSeaGreen" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <Canvas.LayoutTransform>
            <ScaleTransform ScaleY="-1" />
            </Canvas.LayoutTransform>

        </Canvas>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:PointViewModel}">
        <Ellipse Width="3" Height="3" Fill="Red"/>
        </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>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

Mar*_*art 18

由于你Canvas似乎没有固定的宽度和高度,我会把它包括在Viewbox:

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <Viewbox Stretch="Uniform">
            <Canvas x:Name="canvas" Background="DarkSeaGreen">
                <Canvas.LayoutTransform>
                <ScaleTransform ScaleY="-1" />
                </Canvas.LayoutTransform>
            </Canvas>
        </Viewbox>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
Run Code Online (Sandbox Code Playgroud)

或者,将您的整个UserControl放入ViewBox.

  • @Mart:非常有趣,看起来它接近我想要的东西.如果我改变我的代码就像你建议我得到一个InvalidOperationException"ItemsPanelTemplate的VisualTree必须包含一个Panel.'System.Windows.Controls.Viewbox'不是一个Panel." (3认同)
  • 你的问题来自Canvas没有维度的事实.它的父容器使它占用整个可用空间.如果您知道点X和Y的边界,请将它们设置为Canvas Width和Height.这样将Viewbox放在UserControl或ItemsControl周围就会实际拉伸它. (2认同)