好的,抱歉耽搁了,但这是我的问题的工作代码......我希望它对某人有所帮助。
回顾一下,我想做的是生成一个如下所示的 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;
}
}