【问题标题】:WPF Extended Toolkit Property Grid - Edit ExpandableObject titleWPF 扩展工具包属性网格 - 编辑 ExpandableObject 标题
【发布时间】:2014-07-08 20:53:50
【问题描述】:

我正在使用 WPF 扩展工具包属性网格。我正在使用编辑器用户控件来显示对象列表,它看起来像这样:

我的用户希望能够更改“元素”描述中的数字,并让代码调整列表中的元素数量。

{ 删除了不完整的代码,请参阅下面的答案以获取工作代码}

有没有办法让我自己的控件用 TextBox 替换“3 个元素”的标签,这样我就可以处理对文本的更改并更改我的数组?

谢谢, 大卫

【问题讨论】:

  • “3 个元素”的 xaml 在哪里?是绑定到WTFPropertyLabel 吗?
  • lll - “3 个元素”没有 xaml,它是由 MaterialElementList 上的 toString 函数生成的
  • 不,没有魔法正在发生。您的控件中有一个模板(XAML),这就是它生成“3 个元素”的原因
  • 我已经解决了这个问题,它涉及一个 ExpandableObjectEditor(如图)。我将在今天晚些时候发布解决方案。

标签: c# wpf xaml user-controls propertygrid


【解决方案1】:

好的,抱歉耽搁了,但这是我的问题的工作代码......我希望它对某人有所帮助。

回顾一下,我想做的是生成一个如下所示的 PropertyGrid 条目:

总而言之,您需要做的是创建两个用户控件属性网格编辑器,一个用于摘要行(上面的旋转框和元素标签),另一个用于数据列表。所有相关代码如下:

所以,首先,这里是 Element 类:

public class Element 
{
    public Element(int number, double wtf)
    {
        Number = number;
        WTF = wtf;
    }

    public int Number { get; set; }

    public double WTF { get; set; }
}

我还有一个元素的视图模型:

public class ElementViewModel : XTRRABase
{
    public Element _element;

    public ElementViewModel(Element element)
    {
        _element = element;
    }

    public int Number
    {
        get { return _element.Number; }
        set { _element.Number = value; NotifyPropertyChanged(); }
    }

    public double WTF
    {
        get { return _element.WTF; }
        set { _element.WTF = value; NotifyPropertyChanged(); }
    }

    public String ElementInfo
    {
        get { return XTRRAApp.Application.AtomicElementList.GetElements()[Number]; }
        set { }
    }
}

ElementInfo 属性返回元素名称(如示例中的“6 (Carbon)”)。

在父视图模型(包含 Elements 属性的对象)中,该属性如下所示:

    ElementListViewModel _elements;
    [PropertyOrder(4), DisplayName("Elements")]
    [ExpandableObject]
    [Editor(typeof(ElementHeaderUCEditor), typeof(ElementHeaderUCEditor))]
    public ElementListViewModel Elements
    {

        get { return (_elements = new ElementListViewModel(_material.Elements) ); }
        set {}
    }

请注意,此对象既是ExpandableObject,又具有定义的编辑器ElementHeaderUCEditor

ElementHeaderUCEditor 定义了 IntegerUpDown 旋转框和“元素”标签。它的 XAML 看起来像这样:

<UserControl x:Class="XTRRAApp.View.Editors.ElementHeaderUCEditor"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit">
    <StackPanel Orientation="Horizontal" Background="White">
        <xctk:IntegerUpDown Text="{Binding Value.Count,UpdateSourceTrigger=PropertyChanged}" Width="100" Margin="2,2,2,2" ParsingNumberStyle="Integer"/>
        <Label Content="Elements" Width="Auto" Margin="2,2,2,2"/>
    </StackPanel>
</UserControl>

和代码隐藏:

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

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(ElementListViewModel), typeof(ElementHeaderUCEditor),
                                                                    new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    public ElementListViewModel Value
    {
        get { return (ElementListViewModel)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

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

接下来,这里是为 List 提供数据的 ElementListViewModel:

[DisplayName("Elements")]
public class ElementListViewModel : XTRRABase
{
    protected List<Element> _elements;

    public ElementListViewModel(List<Element> elements)
    {
        _elements = elements;
    }

    [Browsable(false)]
    public int Count
    {
        get { return _elements.Count; }
        set 
        { 
            while(value < _elements.Count)
            {
                _elements.RemoveAt(_elements.Count - 1);
            }
            while(value > _elements.Count)
            {
                _elements.Add(new Element(0,0));
            }
            NotifyPropertyChanged();
            NotifyPropertyChanged("Elements");
        }
    }

    [PropertyOrder(1), DisplayName("Elements")]
    [Editor(typeof(ElementUCEditor), typeof(ElementUCEditor))]
    public ObservableCollection<ElementViewModel> Elements
    {
        get
        {
            ObservableCollection<ElementViewModel> list = new ObservableCollection<ElementViewModel>();

            foreach(Element element in _elements)
            {
                list.Add(new ElementViewModel(element));
            }
            return list;
        }
        set { }
    }
}

XTRRABase 只是我用来避免重复通知代码的通用基类:

public abstract class XTRRABase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

如您所见,元素是使用另一个用户控件“ElementUCEditor”显示的,它的 XAML 如下所示:

及其背后的代码:

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

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(ElementListViewModel), typeof(ElementUCEditor),
                                                                                    new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    public ElementListViewModel Value
    {
        get { return (ElementListViewModel)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

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

}

【讨论】:

    【解决方案2】:

    我使用 propertyGrid 作为 CustomEditor:

    public partial class PropertyGridEditor : ITypeEditor
    {
        public PropertyGridEditor()
        {
            InitializeComponent();
        }
    
        public FrameworkElement ResolveEditor(PropertyItem propertyItem)
        {
            if (propertyItem.Value != null)
            {
                var objects = propertyItem.Value;
                foreach (var o in (IEnumerable)objects)
                {
                    var propertyGrid = new Xceed.Wpf.Toolkit.PropertyGrid.PropertyGrid
                    {
                        IsCategorized = false,
                        IsMiscCategoryLabelHidden = true,
                        ShowAdvancedOptions = false,
                        ShowDescriptionByTooltip = true,
                        ShowPreview = false,
                        ShowSearchBox = false,
                        ShowSortOptions = false,
                        ShowTitle = true,
                        ShowSummary = false,
                        SelectedObject = o,
                    };
                    Container.Children.Add(propertyGrid);
                }
            }
    
            return this;
        }
    }
    

    XAML

    <UserControl x:Class="ibKastl.Helper.UserControls.PropertyGrid.Editor.PropertyGridEditor"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <StackPanel Orientation="Vertical" Name="Container">
        </StackPanel>
    </UserControl>
    

    因此您可以将任何 Enumerable 添加到属性网格中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-19
      • 2023-03-18
      • 2012-11-16
      • 1970-01-01
      • 2012-03-08
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      相关资源
      最近更新 更多