ItemsControl在WPF中有多个DataTemplate

问题描述 投票:0回答:2

我想在画布上绘制不同的形状。如何在画布中显示ArrowsItems ObservableCollection和CircleItems ObservableCollecton中的对象?我也在创建Shapes ObservableCollection,包括每个Circle和Arrows项目。我认为原因在于数据绑定但不知道在哪里。

目标是生成然后以编程方式绘制圆圈和箭头的可能性。

  <Button Grid.Row="1" MaxWidth="1000" Command="{Binding CreateEllipse}">Utwórz</Button>
        <Viewbox Grid.Row="2" Margin="0 20 0 0" Stretch="Uniform" StretchDirection="Both" VerticalAlignment="Stretch">
          <ItemsControl Name="Shape" ItemsSource="{Binding Shapes}">
            <ItemsControl.ItemsPanel>
              <ItemsPanelTemplate>
                <Canvas Width="2000" Height="1200" />
              </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
              <Style TargetType="ContentPresenter">
                <Setter Property="Canvas.Left" Value="{Binding X, Mode=TwoWay}"/><Setter Property="Canvas.Top" Value="{Binding Y, Mode=TwoWay}"/>
              </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.Resources>
              <DataTemplate DataType="{x:Type core:CircleItem}">
                <Viewbox Width="{Binding Width}" Height="{Binding Height}">
                  <!--MouseMove="Viewbox_MouseMove"-->
                  <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseMove">
                      <i:InvokeCommandAction Command="{Binding DataContext.MyCommand, ElementName=Shape}" CommandParameter="{Binding}" />
                    </i:EventTrigger>
                  </i:Interaction.Triggers>

                  <i:Interaction.Behaviors>
                    <local:DragBehavior/>
                  </i:Interaction.Behaviors>
                  <Grid>
                    <Grid.RenderTransform>
                      <TranslateTransform X="{Binding TransformX}" Y="{Binding TransformY}" />
                    </Grid.RenderTransform>
                    <Ellipse Width="{Binding Width}" Height="{Binding Height}" Fill="{Binding Color}" />
                    <TextBlock HorizontalAlignment="Center" Text="{Binding Text}" TextAlignment="Center" VerticalAlignment="Center" />
                  </Grid>
                </Viewbox>
              </DataTemplate>
              <DataTemplate DataType="{x:Type core:ArrowItem}">
                <Line X1="{Binding X1}" Y1="{Binding Y1}" X2="{Binding X2}" Y2="{Binding Y2}" Stroke="{Binding Color}" StrokeThickness="{Binding StrokeThickness}" />
              </DataTemplate>
            </ItemsControl.Resources>
          </ItemsControl>
        </Viewbox>

也在我的ViewModel中:

public ObservableCollection<CircleItem> CircleItems { get; set; }
public ObservableCollection<ArrowItem> ArrowItems { get; set; }
public CompositeCollection Shapes { get; set; }

在将CircleItem类的一些对象添加到CircleItems并将ArrowItem添加到ArrowItems之后:

    CompositeCollection coll = new CompositeCollection();
    coll.Add(new CollectionContainer() { Collection = CircleItems });
    coll.Add(new CollectionContainer() { Collection = ArrowItems });
    Shapes = coll;
c# wpf mvvm datatemplate itemscontrol
2个回答
0
投票

确保在将视图模型分配给DataContext之前初始化Shapes属性。集合属性应该只是readonly,否则你必须从他们的setter发出属性更改通知。

public class ViewModel
{
    public ObservableCollection<CircleItem> CircleItems { get; }
        = new ObservableCollection<CircleItem>();

    public ObservableCollection<ArrowItem> ArrowItems { get; }
        = new ObservableCollection<ArrowItem>();

    public CompositeCollection Shapes { get; }
        = new CompositeCollection();

    public ViewModel()
    {
        Shapes.Add(new CollectionContainer { Collection = CircleItems });
        Shapes.Add(new CollectionContainer { Collection = ArrowItems });
    }
}

-1
投票

如果我理解正确,您希望为不同的数据类型设置不同的模板。这很容易搞定。其中一种方式(可能是最简单的方式):

  • 为您要显示的每种类型创建数据模板
  • 创建某种数据模板,选择合适的模板: <!-- Data template for arrows --> <DataTemplate x:Key="ArrowsDataTemplate" DataType="{x:Type core:ArrowItem}"> <!-- Create here your template for arrows --> </DataTemplate> <!-- create data templates for other stuff and then "selector" data template --> <DataTemplate x:Key="ContentDataTemplate"> <ContentPresenter x:Name="itemContentPresenter" ContentTemplate="{StaticResource CircleDataTemplate}" <!-- just the default one --> Content="{TemplateBinding Content}"/> <DataTemplate.Triggers> <DataTrigger Binding="{Binding MyItemTypeAsEnum}" Value="Arrow"> <Setter TargetName="itemContentPresenter" Property="ContentTemplate" Value="{StaticResource ArrowsDataTemplate"/> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> <!-- Now in your control (for example content control), where you show this stuff, do: --> <ContentControl ContentTemplate="{StaticResource ContentDataTemplate}"/>

现在,我假设您有一个基本Item,其属性为MyItemTypeAsEnum,它将为CircleItem提供Circle,为ArrowItem提供Arrow等。但是如果您没有这样的属性,您应该能够从您的viewmodel获取布尔值你是否这个项目是Circle等等。

进入主控件时,当您显示内容时,必须将ContentTemplate设置为“选择器”模板。

© www.soinside.com 2019 - 2024. All rights reserved.