【问题标题】:Storing properties of objects in C#/WPF在 C#/WPF 中存储对象的属性
【发布时间】:2012-06-19 01:04:18
【问题描述】:

我允许用户从工具箱中拖放一些对象,当然每个object 都有一个唯一的ID。一旦使用了对象,假设放置在gridcanvas 上,我需要显示它的属性,所以我需要一个对象数组,其中每个对象都可以拥有自己的属性。

你能给我一些建议和指导,告诉我如何实现一个类来处理多个对象,同时每个对象可以保持假设 10 个属性吗?

【问题讨论】:

  • 您需要提供有关问题的更多详细信息。
  • 听起来你想要一个对象列表。或者如果您想通过它的唯一键访问每个对象,则可能是字典。
  • 在您的类中使用 ObservableDictionary 或 WPF PropertyGrid。

标签: c# .net wpf properties


【解决方案1】:

你能给我一些关于如何实现类的建议和指导吗 处理多个对象,而每个对象都可以坚持让我们说 10 个属性?

你不需要实现这样的类。我处理这个问题的方法是为工具箱中的所有对象(例如ToolboxItem)提供一个公共基类,它只公开工具箱中所有项目共有的属性和功能。

public abstract class ToolboxItem
{
    public string Name { get; set; }
    public Point Position { get; set; }
}

然后您可以从此类 E.G. 派生您的特定项目。 TextToolboxItemRectangleToolboxItem(或任何你想要的)。然后,派生类可以只公开它们需要的属性。

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; } }
}

要在用户界面中显示此信息,我将执行以下操作:

  • 使用网格将视图分成两部分。第一个是显示所选项目属性的位置,第二个显示“设计表面”
  • 使用ContentPresenter 显示选定项的属性。
  • 使用 ListBox 和自定义 ItemsPanelItemContainerStyle 将您的项目“绘制”到设计图面上。
  • 使用 DataTemplate 告诉 WPF 如何在“属性网格”和“设计图面”中呈现每个项目(This 帖子描述了如何为不同的对象使用不同的 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>

最终结果如下所示:

请注意,所选项目的属性显示在窗口的左侧。

现在这个解决方案目前非常粗糙,但确实为您提供了进一步开发的起点。改进的想法包括:

  • 将代码重构到 viewModel 中,使其符合 MVVM。
  • 处理“设计图面”上的项目拖放。
  • 更改属性网格的“ContentPresenter”,为显示和编辑所选对象的属性提供更丰富的支持。

【讨论】:

    【解决方案2】:

    最好的解决方案是使用PropertyGrid 控件;您的应用程序看起来与 Visual Studio 类似,您的实现也将与此类似。

    查看这个 SO question 以了解您拥有的可用 PropertyGrid 选项 - Is there a Property Dialog control that i can use in my WPF App?

    现在您可以为每个控件定义一个类并为该控件声明正常的 CLR 属性;您不想在 PropertyGrid 中显示的属性可以用 BrowsableAttribute 标记,PropertyGrid 会遵守这一点。

    如果您想更好地控制显示的属性,您可以创建自己的 custom attribute 并修改 PropertyGrid 实现以使用该属性并显示标有该属性的属性。

    【讨论】:

    • 谢谢。是的,这似乎是我需要的。
    猜你喜欢
    • 2021-07-18
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 2014-02-20
    • 1970-01-01
    • 2022-01-19
    相关资源
    最近更新 更多