将Silverlight控件集合绑定到网格-是否可能?

将Silverlight控件集合绑定到网格-是否可能?,silverlight,mvvm,binding,Silverlight,Mvvm,Binding,我对Silverlight有点陌生,现在我正在开发一个地图应用程序。我有一组自定义控件(地图标记、POI等)。每个控件都有一个类型点的属性“Location”,其中Location.X表示控件的Canvas.Left,Location.Y表示控件的Canvas.Top 我正在尝试将我的接口重构为MVVM模式。我想这样做: <ItemsControl ItemsSource="{Binding Path=Controls}"> <ItemsControl.ItemsPan

我对Silverlight有点陌生,现在我正在开发一个地图应用程序。我有一组自定义控件(地图标记、POI等)。每个控件都有一个类型点的属性“Location”,其中
Location.X
表示控件的
Canvas.Left
Location.Y
表示控件的
Canvas.Top

我正在尝试将我的接口重构为MVVM模式。我想这样做:

<ItemsControl ItemsSource="{Binding Path=Controls}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas Background="Beige" IsItemsHost="True" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Model, Mode=OneWay}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Canvas.Top" Value="{Binding Path=Top, Mode=OneWay}" />
            <Setter Property="Canvas.Left" Value="{Binding Path=Left, Mode=OneWay}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>
<ItemsControl x:Name="LayoutRoot" DataContext="{StaticResource model}"
            ItemsSource="{Binding MyCollection}" 
            HorizontalAlignment="Left" VerticalAlignment="Top">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas x:Name="host"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid x:Name="item" Background="Transparent">
                <Grid.RenderTransform>
                    <TranslateTransform X="{Binding Location.X}" Y="{Binding Location.Y}"/>
                </Grid.RenderTransform>

                // other stuff here
                ...
                //

            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>

</ItemsControl>
  • 假设我的控件在画布中。我想要一些像:

  • 在我的自定义控件中,我希望有如下内容:


  • 可能吗?也许有更好的方法?

    我认为可以使用ItemsControl控件来实现这一点

    假设您创建了一个holder控件,该控件保存控件的位置+您选择的更多信息。 我称之为“ControlDefinition.cs”:

    然后,在我的模型(ViewModel.cs)中,我创建了一个此类的ObservableCollection:

    public static readonly DependencyProperty ControlsProperty = DependencyProperty.Register("Controls", typeof(ObservableCollection<ControlDefinition>), typeof(MainWindow), new PropertyMetadata(null));
    public new ObservableCollection<ControlDefinition> Controls
    {
        get { return (ObservableCollection<ControlDefinition>)GetValue(ControlsProperty); }
        set
        {
            SetValue(ControlsProperty, value);
            NotifyPropertyChanged("Controls");
        }
    }
    
    public static readonly dependencProperty ControlsProperty=dependencProperty.Register(“控件”、typeof(observeCollection)、typeof(主窗口)、new PropertyMetadata(null));
    公共新的可观察收集控件
    {
    get{return(ObservableCollection)GetValue(ControlsProperty);}
    设置
    {
    设置值(控件属性、值);
    NotifyPropertyChanged(“控制”);
    }
    }
    
    然后,在同一个模型中,我初始化集合并添加4个虚拟控件:

    this.Controls = new ObservableCollection<ControlDefinition>();
    this.Controls.Add(new ControlDefinition() { Top = 10, Left = 10, Model = "One" });
    this.Controls.Add(new ControlDefinition() { Top = 50, Left = 10, Model = "Two" });
    this.Controls.Add(new ControlDefinition() { Top = 90, Left = 10, Model = "Three" });
    
    this.Controls=新的ObservableCollection();
    添加(新的ControlDefinition(){Top=10,Left=10,Model=“One”});
    Add(newControlDefinition(){Top=50,Left=10,Model=“Two”});
    Add(newControlDefinition(){Top=90,Left=10,Model=“Three”});
    
    我的视图(VIEW.xaml)是这样的:

    <ItemsControl ItemsSource="{Binding Path=Controls}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas Background="Beige" IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Path=Model, Mode=OneWay}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Top" Value="{Binding Path=Top, Mode=OneWay}" />
                <Setter Property="Canvas.Left" Value="{Binding Path=Left, Mode=OneWay}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
    
    <ItemsControl x:Name="LayoutRoot" DataContext="{StaticResource model}"
                ItemsSource="{Binding MyCollection}" 
                HorizontalAlignment="Left" VerticalAlignment="Top">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas x:Name="host"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="item" Background="Transparent">
                    <Grid.RenderTransform>
                        <TranslateTransform X="{Binding Location.X}" Y="{Binding Location.Y}"/>
                    </Grid.RenderTransform>
    
                    // other stuff here
                    ...
                    //
    
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    
    </ItemsControl>
    
    
    
    请注意,我在“DataTemplate”中显示了一个“TextBlock”控件,缺少您的控件。 我在TextBlock的“Text”属性中显示了“Model”属性(我定义为“String”)。可以将“Model”属性指定给控件的“DataContext”属性,如示例所示


    希望有帮助

    所以,在谷歌搜索、询问和阅读之后,我找到了一个解决方案:

  • 应该有一个实现INotifyPropertyChanged接口的模型。从属属性不是必需的。下面是一个例子:

    public class MyItemModel: INotifyPropertyChanged
    {
        // INotifyPropertyChanged implementation
        ...
        //
    
        private Point _location;
        public Point Location
        {
            get { return Location; }
            set { _location = value; NotifyPropertyChanged("Location"); }
        }
    
        // any other fields
        ...
        //
    }
    
  • 然后,假设我们有一个包含MyItemModels集合的模型:

    public class MyModel: INotifyPropertyChanged
    {
        // INotifyPropertyChanged implementation
        ...
        //
    
        private ObservableCollection<MyItemModel> _myCollection;
        public ObservableCollection<MyItemModel> MyCollection
        {
            get { return _myCollection; }
            set { _myCollection = value; NotifyPropertyChanged("MyCollection"); }
        }
    }
    
    公共类MyModel:INotifyPropertyChanged
    {
    //INotifyPropertyChanged实现
    ...
    //
    私人可观察收集(myCollection);;
    公共可观测集合MyCollection
    {
    获取{return\u myCollection;}
    设置{u myCollection=value;NotifyPropertyChanged(“myCollection”);}
    }
    }
    
  • 然后,在XAML中,我们应该像这样使用ItemsControl:

    <ItemsControl ItemsSource="{Binding Path=Controls}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas Background="Beige" IsItemsHost="True" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Path=Model, Mode=OneWay}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemContainerStyle>
            <Style>
                <Setter Property="Canvas.Top" Value="{Binding Path=Top, Mode=OneWay}" />
                <Setter Property="Canvas.Left" Value="{Binding Path=Left, Mode=OneWay}" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
    
    <ItemsControl x:Name="LayoutRoot" DataContext="{StaticResource model}"
                ItemsSource="{Binding MyCollection}" 
                HorizontalAlignment="Left" VerticalAlignment="Top">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas x:Name="host"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid x:Name="item" Background="Transparent">
                    <Grid.RenderTransform>
                        <TranslateTransform X="{Binding Location.X}" Y="{Binding Location.Y}"/>
                    </Grid.RenderTransform>
    
                    // other stuff here
                    ...
                    //
    
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    
    </ItemsControl>
    
    
    //这里还有其他东西
    ...
    //
    

  • 很有魅力:)谢谢大家。

    非常感谢您的回答,但silverlight中一定有不同的东西。例如,在为ItemPanelTemplate的画布中,缺少属性IsItemsHost,ItemsControl.ItemContainerStyle也是如此(ItemsControl中根本没有ItemContainerStyle属性)。我试图删除丢失的代码,但没有成功-我的ItemsControl只显示一个控件。我还试着只写ItemTemplate部分,我让所有的项目垂直对齐,因为它们在StackPanel中。