2012-11-27 36 views
0

我對Silverlight有點新,現在我正在開發一個地圖應用程序。我有一組自定義控件(地圖標記,POI等)。每個控件都有一個類型爲Point的屬性「位置」,其中Location.X表示控件的Canvas.LeftLocation.Y表示控件的Canvas.Top綁定Silverlight控件集合到網格 - 可能與否?

我想重構我的MVVM模式的接口。我想要做這樣的事情:

  1. 說我的控件在Canvas中。我想有這樣的:

    <Canvas DataContext="{StaticResource myModel}" ItemsSource="{Binding controlsCollection}">

    <Canvas.ItemTemplate> ... </Canvas.ItemTemplate>

    </Canvas>

  2. 在我的自定義控件我想有這樣的:

    <myCustomControl DataContext="{StaticResource myControlModel}" Canvas.Left="{Binding Location.X}" Canvas.Top="{Binding Location.Y}" />

這可能嗎?也許有更好的方法?

回答

0

所以,谷歌搜索,詢問和閱讀所有次後,在這裏我找到了一個解決方案:

  1. 應該有實現INotifyPropertyChanged接口的典範。 DependencyProperties不是必需的。這裏有一個例子:

    public class MyItemModel: INotifyPropertyChanged 
    { 
        // INotifyPropertyChanged implementation 
        ... 
        // 
    
        private Point _location; 
        public Point Location 
        { 
         get { return Location; } 
         set { _location = value; NotifyPropertyChanged("Location"); } 
        } 
    
        // any other fields 
        ... 
        // 
    } 
    
  2. 然後說我們有MyItemModels集合的模式:

    public class MyModel: INotifyPropertyChanged 
    { 
        // INotifyPropertyChanged implementation 
        ... 
        // 
    
        private ObservableCollection<MyItemModel> _myCollection; 
        public ObservableCollection<MyItemModel> MyCollection 
        { 
         get { return _myCollection; } 
         set { _myCollection = value; NotifyPropertyChanged("MyCollection"); } 
        } 
    } 
    
  3. 然後,在XAML,我們應該使用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> 
    

工程就像一個魅力:)謝謝大家。

0

我認爲這是可以使用ItemsControl控件。

假設您創建一個持有者控件,持有控件的位置+您選擇的更多信息。 我稱之爲 「ControlDefinition.cs」:

public class ControlDefinition : DependencyObject, INotifyPropertyChanged 
{ 
    public static readonly DependencyProperty TopProperty = DependencyProperty.Register("Top", typeof(Double), typeof(ControlDefinition), new PropertyMetadata(0d)); 
    public static readonly DependencyProperty LeftProperty = DependencyProperty.Register("Left", typeof(Double), typeof(ControlDefinition), new PropertyMetadata(0d)); 
    public static readonly DependencyProperty ModelProperty = DependencyProperty.Register("Model", typeof(Object), typeof(ControlDefinition), new PropertyMetadata(null)); 

    public Double Top 
    { 
     get { return (Double)GetValue(TopProperty); } 
     set 
     { 
      SetValue(TopProperty, value); 
      NotifyPropertyChanged("Top"); 
     } 
    } 
    public Double Left 
    { 
     get { return (Double)GetValue(LeftProperty); } 
     set 
     { 
      SetValue(LeftProperty, value); 
      NotifyPropertyChanged("Left"); 
     } 
    } 
    public Object Model 
    { 
     get { return (Object)GetValue(ModelProperty); } 
     set 
     { 
      SetValue(ModelProperty, value); 
      NotifyPropertyChanged("Model"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String aPropertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(aPropertyName)); 
    } 
} 

然後,在我的模型(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"); 
    } 
} 

然後,在相同的模型,我初始化集合,並增加了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" }); 

而且我有我的觀點(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> 

請注意,我在我的「DataTemplate」中顯示「TextBlock」控件,缺乏您的控制權。 我在TextBlock的「Text」屬性中顯示「Model」屬性(我已將其定義爲「String」)。您可以將「Model」屬性分配給控件的「DataContext」屬性,如示例中所示。

希望它有幫助!

+0

非常感謝您的回答,但silverlight中必須有所不同。例如,在Canvas中ItemPanelTemplate屬性IsItemsHost缺失,因此ItemsControl.ItemContainerStyle(ItemsControl中根本沒有ItemContainerStyle屬性)。 我試圖刪除丟失的代碼,但它不起作用 - 我的ItemsControl只顯示一個控件。 我也嘗試只寫ItemTemplate部分,我得到所有項目垂直對齊,因爲它們在StackPanel中。 –

相關問題