在PropertyGrid控件中显示只读属性

 峰的紫色摩天轮 发布于 2023-02-06 18:28

我正在使用WPF扩展工具包来显示Team对象的属性.现在其中一个属性是人物集合.没问题,我得到一个很好的下拉,当我点击时,向我显示每个人的姓名和年龄.

在此输入图像描述

现在的问题是我实际上并不希望将我的Collection公开为public.但是,只要我将其setter设为私有,就会禁用该属性,以防止用户看到Person集合和人员详细信息:

在此输入图像描述

当它的setter是私有的时候我该如何显示我的Person Collection?我可以使用XAML模板执行此操作吗?如果是这样的话?我正在使用MVVM,因此我不想在代码中添加任何内容.

更新

好的,所以@tencntraze的解决方案让我大部分都在那里 - 谢谢.但是它对于对象的集合不起作用,这是我在我的情况下得到的.此外,它还可以简化为使用CollectionControlDialog而不是下面实现的自定义ReadOnlyCollectionViewer.

XAML


    
        
        

代码隐藏

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

    // Use typeof(object) to allow for any Collection
    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();
    }
}

Matt.. 10

我认为你最好的选择是根据Xceed文档实现自己的编辑器.然后,您可以向用户提供要显示的任何UI,而无需将值提交回基础对象.请注意,此方法适用于私有setter以及没有任何setter的属性.

ReadOnlyCollectionEditor

XAML


    

代码隐藏

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

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value", typeof (IList), typeof (ReadOnlyCollectionEditor), new PropertyMetadata(default(IList)));

    public IList Value
    {
        get { return (IList)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)
    {
        ReadOnlyCollectionViewer viewer = new ReadOnlyCollectionViewer {DataContext = this};
        viewer.ShowDialog();
    }
}

ReadOnlyCollectionViewer


    

示例属性类

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

    public string StringProperty { get; set; }

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

分配到属性网格

this.propertyGrid.SelectedObject = new MyDataObjects();

结果

主窗口

在此输入图像描述

编辑

我意识到你想使用MVVM,我在使用WPF时非常鼓励,但是为了这个示例的目的,我认为保持简单有助于说明这一点,否则它会带来其他问题,比如从MVVM显示模态对话框,所以我只需点击一下按钮即可显示对话框.

1 个回答
  • 我认为你最好的选择是根据Xceed文档实现自己的编辑器.然后,您可以向用户提供要显示的任何UI,而无需将值提交回基础对象.请注意,此方法适用于私有setter以及没有任何setter的属性.

    ReadOnlyCollectionEditor

    XAML

    <UserControl x:Class="WpfApplication2.ReadOnlyCollectionEditor"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 x:Name="uc">
        <Button Click="Button_OnClick"  />
    </UserControl>
    

    代码隐藏

    public partial class ReadOnlyCollectionEditor : UserControl, ITypeEditor
    {
        public ReadOnlyCollectionEditor()
        {
            InitializeComponent();
        }
    
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
            "Value", typeof (IList<string>), typeof (ReadOnlyCollectionEditor), new PropertyMetadata(default(IList<string>)));
    
        public IList<string> Value
        {
            get { return (IList<string>)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)
        {
            ReadOnlyCollectionViewer viewer = new ReadOnlyCollectionViewer {DataContext = this};
            viewer.ShowDialog();
        }
    }
    

    ReadOnlyCollectionViewer

    <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"  >
        <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();
    

    结果

    主窗口

    在此输入图像描述

    编辑

    我意识到你想使用MVVM,我在使用WPF时非常鼓励,但是为了这个示例的目的,我认为保持简单有助于说明这一点,否则它会带来其他问题,比如从MVVM显示模态对话框,所以我只需点击一下按钮即可显示对话框.

    2023-02-06 18:29 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有