複数のオブジェクトを処理するクラスを実装する方法について、アドバイスと方向性を教えてください。各オブジェクトは、たとえば 10 個のプロパティを保持できますか?
そのようなクラスを実装する必要はありません。この問題を処理する方法は、ツールボックスToolboxItem
内のすべてのアイテムに共通のプロパティと機能のみを公開する、ツールボックス内のすべてのオブジェクト (たとえば) に共通の基本クラスを用意することです。
public abstract class ToolboxItem
{
public string Name { get; set; }
public Point Position { get; set; }
}
次に、このクラス EG TextToolboxItem
and RectangleToolboxItem
(または必要なもの) から特定のアイテムを派生させることができます。派生クラスは、必要なプロパティのみを公開できます。
public class TextToolboxItem : ToolboxItem
{
public string Text { get; set; }
}
public class RectangleToolboxItem : ToolboxItem
{
public Rect Bounds { get; set; }
}
これらを保存するには、次のような一般的なコレクションを使用できます。
ObservableCollection<ToolboxItem> items = new ObservableCollection<ToolboxItems>();
アイテムが派生する限り、ToolboxItem
それらはすべて単一のコレクション内に保持でき、個々のプロパティはすべて WPF のデータ バインディング機能を使用してバインドできます。
次に、次の方法でデータを作成して公開できます。
public partial class MainWindow : Window
{
private ObservableCollection<ToolboxItem> items;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
items = new ObservableCollection<ToolboxItem>
{
new TextToolboxItem { Name = "primaryText",
Text = "Hello world",
Position = new Point(40, 130) },
new TextToolboxItem { Name = "secondaryText",
Text = "Hello world (again)",
Position = new Point(200, 30) },
new RectangleToolboxItem { Position = new Point(50,300),
Name = "Rect1",
Bounds = new Rect(0, 0, 150, 85) },
};
}
public ObservableCollection<ToolboxItem> Items { get { return items; } }
}
この情報をユーザー インターフェイスに表示するには、次のようにします。
- グリッドを使用して、ビューを 2 つのセクションに分割します。1 つ目は選択した項目のプロパティが表示される場所で、2 つ目は「デザイン サーフェイス」が表示されます。
- を使用して、選択
ContentPresenter
したアイテムのプロパティを表示します。
ListBox
カスタムItemsPanel
とを使用してItemContainerStyle
、アイテムをデザイン サーフェイスに「描画」します。
- a
DataTemplate
を使用して、「プロパティ グリッド」と「デザイン サーフェイス」の両方で各アイテムをレンダリングする方法を WPF に指示します (この投稿では、オブジェクトごとに異なる を使用する方法について説明しDataTemplate
ます)。
これを実現するために必要な xaml を以下に示します。
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="7*" />
</Grid.ColumnDefinitions>
<ContentPresenter Content="{Binding ElementName=listBox, Path=SelectedItem}"
Margin="5">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type this:TextToolboxItem}">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Position}"/>
<TextBlock Text="{Binding Text}"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type this:RectangleToolboxItem}">
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Position}"/>
<TextBlock Text="{Binding Bounds}"/>
</StackPanel>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
<ListBox x:Name="listBox" Grid.Column="1"
Margin="5" ItemsSource="{Binding Items}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type this:TextToolboxItem}">
<TextBox Text="{Binding Text}"
Margin="10"/>
</DataTemplate>
<DataTemplate DataType="{x:Type this:RectangleToolboxItem}">
<Rectangle Width="{Binding Bounds.Width}"
Height="{Binding Bounds.Height}"
Stroke="DarkRed" Fill="Pink"/>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding Position.X}"/>
<Setter Property="Canvas.Top" Value="{Binding Position.Y}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
最終結果は次のようになります。
選択した項目のプロパティがウィンドウの左側のセクションに表示されていることに注意してください。
現在、このソリューションは非常に粗雑ですが、これをさらに開発するための出発点を示しています。改善のためのアイデアは次のとおりです。
- MVVM に準拠するように、コードを viewModel にリファクタリングします。
- 「デザイン サーフェイス」でアイテムのドラッグ アンド ドロップを処理します。
- プロパティ グリッドの「ContentPresenter」を変更して、選択したオブジェクトのプロパティを表示および編集するためのより豊富なサポートを提供します。