XAML 在集合中绘制矩形列表

3hvapo4f  于 2023-02-10  发布在  其他
关注(0)|答案(1)|浏览(95)

我的WPF应用程序有一个ViewModel,该ViewModel有一个ObservableCollection,该集合保存Item类型的对象。每个Item都有一种颜色和一个绘制在画布上的Rect:
项目分类:

public class Item
{
    public Color ItemColor {get; set;}
    public Rect ScaledRectangle {get; set;}
}

XAML:

<Grid>
    <ItemsControl Name="Items" ItemsSource="{Binding Items, Mode=TwoWay}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <local:ItemView  Visibility="Visible">
                    <local:ItemView.Background>
                        <SolidColorBrush Color="{Binding ItemColor}"/>
                        </local:ItemView.Background>
                    </local:ItemView>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="{x:Type ContentPresenter}">
                    <Setter Property="Canvas.Left" Value="{Binding ScaledRectangle.Left}"/>
                    <Setter Property="Canvas.Top" Value="{Binding ScaledRectangle.Top}"/>
                    <Setter Property="FrameworkElement.Width" Value="{Binding ScaledRectangle.Width}"/>
                    <Setter Property="FrameworkElement.Height" Value="{Binding ScaledRectangle.Height}"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Grid>

在我的ViewModel中,我所要做的就是向ObservableCollection添加一个新的Item,以便将其绘制在屏幕上。
这样做效果很好,但现在我发现需要将ScaledRectangle属性更改为某种集合。我想修改此XAML以绘制ScaledRectangles集合中的每个矩形。是否可以修改此XAML,以便将ViewModel功能保留为类似viewModel.AddNewItem(newItem)的内容?

eivnm1vs

eivnm1vs1#

您必须修改ItemsView以支持处理Rect的集合,而不是单个Rect

    • 项目视图. cs**
public class ItemsView : Control
{
  public Item DataSource
  {
    get => (Item)GetValue(DataSourceProperty);
    set => SetValue(DataSourceProperty, value);
  }

  public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register(
    "DataSource",
    typeof(Item),
    typeof(ItemsView),
    new PropertyMetadata(default(Item), OnDataSourceChanged));

  private Panel ItemsHost { get; set; }
  private Dictionary<Rect, int> ContainerIndexTable { get; }
 
  static ItemsView() 
    => DefaultStyleKeyProperty.OverrideMetadata(typeof(ItemsView), new FrameworkPropertyMetadata(typeof(ItemsView)));

  public ItemsView() 
    => this.ContainerIndexTable = new Dictionary<Rect, int>();

  private static void OnDataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    var this_ = d as ItemsView;
    this_.UnloadRectangles(e.OldValue as Item);
    this_.LoadRectangles(e.NewValue as Item);
  }

  public override void OnApplyTemplate()
  {
    base.OnApplyTemplate();      
    this.ItemsHost = GetTemplateChild("PART_ItemsHost") as Panel;
    LoadRectangles(this.DataSource);
  }

  private void UnloadRectangles(Item item)
  {
    if (item is null
      || this.ItemsHost is null)
    {
      return;
    }

    foreach (Rect rectangleDefinition in item.ScaledRectangles)
    {
      if (this.ContainerIndexTable.TryGetValue(rectangleDefinition, out int containerIndex))
      {
        this.ItemsHost.Children.RemoveAt(containerIndex);
      }
    }
  }

  private void LoadRectangles(Item item)
  {
    if (item is null
      || this.ItemsHost is null)
    {
      return;
    }

    foreach (Rect rectangleDefinition in item.ScaledRectangles)
    {
      var container = new Rectangle()
      {
        Height = rectangleDefinition.Height,
        Width = rectangleDefinition.Width,
        Fill = new SolidColorBrush(item.ItemColor)
      };

      Canvas.SetLeft(container, rectangleDefinition.Left);
      Canvas.SetTop(container, rectangleDefinition.Top);

      int containerIndex = this.ItemsHost.Children.Add(container);
      _ = this.ContainerIndexTable.TryAdd(rectangleDefinition, containerIndex);
    }
  }
}
    • 德语. xaml**
<Style TargetType="local:ItemsView">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="local:ItemsView">
        <Canvas x:Name="PART_ItemsHost" />
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
    • 主窗口. xaml**
<ItemsControl>
  <ItemsControl.ItemTemplate>
    <DataTemplate DataType="{x:Type local:Item}">
      <local:ItemsView DataSource="{Binding}" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

相关问题