0

私はSilverlightに少し慣れていないので、現在マップアプリを開発しています。カスタムコントロール(マップマーカー、POIなど)のコレクションがあります。すべてのコントロールには、タイプPointのプロパティ「Location」があります。ここで、コントロールの手段は、コントロールのLocation.X手段です。Canvas.LeftLocation.YCanvas.Top

インターフェイスを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}" />

出来ますか?たぶんもっと良い方法がありますか?

4

2 に答える 2

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(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」プロパティに割り当てることができます。

それが役に立てば幸い!

于 2012-12-16T14:40:43.133 に答える
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>
    

チャームのように機能します:)みんなありがとう。

于 2013-02-26T13:57:08.710 に答える