C# 在PropertyGrid控件中显示只读属性

C# 在PropertyGrid控件中显示只读属性,c#,wpf,xaml,mvvm,wpftoolkit,C#,Wpf,Xaml,Mvvm,Wpftoolkit,我正在使用WPF扩展工具包显示团队对象的属性。现在,这些属性之一是一个集合Persons。没问题,我会得到一个很好的下拉列表,当我点击时,它会显示每个人的姓名和年龄 现在的问题是,我实际上不想公开我的收藏。但是,一旦我将其setter设置为private,该属性将被禁用,从而阻止用户查看Person集合和Person详细信息: 当我的Person集合的setter是私有的时,我应该如何显示它?我可以用XAML模板来做这件事吗?如果是,怎么做?我使用的是MVVM,所以我不想在代码中添加任何内容

我正在使用WPF扩展工具包显示团队对象的属性。现在,这些属性之一是一个集合Persons。没问题,我会得到一个很好的下拉列表,当我点击时,它会显示每个人的姓名和年龄

现在的问题是,我实际上不想公开我的收藏。但是,一旦我将其setter设置为private,该属性将被禁用,从而阻止用户查看Person集合和Person详细信息:

当我的Person集合的setter是私有的时,我应该如何显示它?我可以用XAML模板来做这件事吗?如果是,怎么做?我使用的是MVVM,所以我不想在代码中添加任何内容

更新

好的,@tencntraze的解决方案让我在大部分方面都达到了目的-谢谢。 但是,它不适用于对象集合,这就是我的例子中的对象集合。此外,它还可以简化为使用,而不是下面实现的自定义ReadOnlyCollectionViewer

XAML


代码隐藏

public partial class ReadOnlyCollectionEditor : UserControl, ITypeEditor
{
    public ReadOnlyCollectionEditor()
    {
        InitializeComponent();
    }

    // Use typeof(object) to allow for any Collection<T>
    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value", typeof(object), typeof(ReadOnlyCollectionEditor), new PropertyMetadata(default(object)));

    public object Value
    {
        // We are now using object so no need to cast
        get { return GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public FrameworkElement ResolveEditor(Xceed.Wpf.Toolkit.PropertyGrid.PropertyItem propertyItem)
    {
        var binding = new Binding("Value")
        {
            Source = propertyItem,
            Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay
        };
        BindingOperations.SetBinding(this, ValueProperty, binding);
        return this;
    }

    private void Button_OnClick(object sender, RoutedEventArgs e)
    {
        var collectionControlDialog = new CollectionControlDialog
        {
            ItemsSource = (IList)this.Value
        };
        collectionControlDialog.ShowDialog();
    }
}
public分部类ReadOnlyCollectionEditor:UserControl,ITypeEditor
{
公共只读集合编辑器()
{
初始化组件();
}
//使用typeof(object)允许任何集合
公共静态只读DependencyProperty ValueProperty=DependencyProperty.Register(
“值”、typeof(对象)、typeof(只读集合编辑器)、新属性元数据(默认值(对象));
公共对象价值
{
//我们现在正在使用对象,因此不需要强制转换
获取{return GetValue(ValueProperty);}
set{SetValue(ValueProperty,value);}
}
公共FrameworkElement ResolveEditor(Xceed.Wpf.Toolkit.PropertyGrid.PropertyItem PropertyItem)
{
var绑定=新绑定(“值”)
{
来源=属性项目,
Mode=propertyItem.IsReadOnly?BindingMode.OneWay:BindingMode.TwoWay
};
BindingOperations.SetBinding(this,ValueProperty,binding);
归还这个;
}
私有无效按钮\u OnClick(对象发送器,路由目标)
{
var collectionControlDialog=新建collectionControlDialog
{
ItemsSource=(IList)this.Value
};
collectionControlDialog.ShowDialog();
}
}

我认为您最好的选择是实现您自己的编辑器,按照。然后,您就可以向用户提供想要显示的任何UI,而无需将值提交回底层对象。注意,这种方法既适用于私有setter,也适用于没有任何setter的属性

只读集合编辑器

<Window x:Class="WpfApplication2.ReadOnlyCollectionViewer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ReadOnlyCollectionViewer" Height="300" Width="300">
    <ListBox ItemsSource="{Binding Value}" />
</Window>
XAML

结果

public class MyDataObjects
{
    public MyDataObjects()
    {
        this.CollectionProperty = new Collection<string> {"Item 1", "Item 2", "Item 3"};            
        this.StringProperty = "Hi!";
    }

    public string StringProperty { get; set; }

    [Editor(typeof(ReadOnlyCollectionEditor), typeof(ReadOnlyCollectionEditor))]
    public ICollection<string> CollectionProperty { get; private set; } 
}   

编辑

我意识到您想要使用MVVM,这是我在使用WPF时极力鼓励的,但对于本示例而言,我相信保持它的简单有助于说明这一点,否则会引发其他问题,例如,因此我只需单击按钮即可显示对话框

公共收集人员
public Collection<Person> People
{
    get { return _people; }
    set { throw new NotSupportedException(); }
}
{ 获取{return\u people;} 设置{抛出新的NotSupportedException();} }

也许不是最好的解决方案,但它可以与PropertyGrid一起使用,同时防止用户设置新的集合。

您是否尝试过使用只读集合?@Alberto是的,我尝试过,但没有区别。您为什么不希望您的属性公开?你到底想完成什么。是否希望查看列表但无法编辑它,或者可能不更改选择。请你详细说明一下好吗?问得好。我正在使用一个无法真正更改的界面。不过,这是有道理的,因为该接口只有只读属性。我只需要能够向用户显示集合的内容。简单地告诉他们“这是一个集合”并没有多大帮助。您是否在“客户项目资源”一节下查看了此处?在这种情况下,抛出异常不是一个选项。这是一个很好的答案,但是正如您所提到的,它对MVVM不友好。我刚刚问了一些与此方向相同的问题,我想将该按钮的控制权传递给包含PropertyGrid的视图的ViewModel。。。如果您知道答案,请链接此处(plz帮助:)
<Window x:Class="WpfApplication2.ReadOnlyCollectionViewer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ReadOnlyCollectionViewer" Height="300" Width="300">
    <ListBox ItemsSource="{Binding Value}" />
</Window>
public class MyDataObjects
{
    public MyDataObjects()
    {
        this.CollectionProperty = new Collection<string> {"Item 1", "Item 2", "Item 3"};            
        this.StringProperty = "Hi!";
    }

    public string StringProperty { get; set; }

    [Editor(typeof(ReadOnlyCollectionEditor), typeof(ReadOnlyCollectionEditor))]
    public ICollection<string> CollectionProperty { get; private set; } 
}   
this.propertyGrid.SelectedObject = new MyDataObjects();
public Collection<Person> People
{
    get { return _people; }
    set { throw new NotSupportedException(); }
}