正如主题所示,我不想修改CollectionEditorPicker的内容。此控件用于打开嵌套属性列表的浮动窗口。 遗憾的是,RadPropertyGrid不会在现场显示有关该集合的任何信息。 我怎样才能在那里设置一些价值?例如,一个占位符,如"点击此处打开集合"或" xx项目"或"第1项,第2项,第3项......"所以请看一些预览或有关该领域的信息。
我已尝试使用模板选择器,但如果我这样做,则打开的Popup不再可调整大小。它还会丢失默认CollectionEditorPicker中的一些信息。 你能救我吗?
在一个最小的工作范例之下。
XAML:
<Window x:Class="TelerikPropertyGridTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:model="clr-namespace:TelerikPropertyGridTest.Model"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<model:TemplateSelector x:Key="RadPropertyListTemplateSelector">
<!-- Not Working -->
<model:TemplateSelector.CollectionsDataTemplate>
<DataTemplate>
<telerik:RadDropDownButton Content="Test">
<telerik:RadDropDownButton.DropDownContent>
<telerik:CollectionEditor telerik:AutoBindBehavior.UpdateBindingOnElementLoaded="Source"
></telerik:CollectionEditor>
</telerik:RadDropDownButton.DropDownContent>
</telerik:RadDropDownButton>
</DataTemplate>
</model:TemplateSelector.CollectionsDataTemplate>
<model:TemplateSelector.FloatNumberTemplate>
<DataTemplate>
<telerik:RadNumericUpDown telerik:AutoBindBehavior.UpdateBindingOnElementLoaded="Value" />
</DataTemplate>
</model:TemplateSelector.FloatNumberTemplate>
<model:TemplateSelector.IntNumberTemplate>
<DataTemplate>
<telerik:RadNumericUpDown telerik:AutoBindBehavior.UpdateBindingOnElementLoaded="Value"
NumberDecimalDigits="0" />
</DataTemplate>
</model:TemplateSelector.IntNumberTemplate>
</model:TemplateSelector>
</Grid.Resources>
<telerik:RadPropertyGrid Item="{Binding ObjectToBind}"
AutoGeneratingPropertyDefinition="RadPropertyGrid_OnAutoGeneratingPropertyDefinition"
EditorTemplateSelector="{StaticResource RadPropertyListTemplateSelector}">
</telerik:RadPropertyGrid>
</Grid>
</Window>
ViewModel(生成一个随机对象进行测试)
public class MainWindowViewModel : BindableBase
{
private readonly Random _random = new Random();
private IExampleInterface _objectToBind;
public MainWindowViewModel()
{
this.ObjectToBind = new ExampleImplementation
{
SomeBooleanValue = this._random.Next() % 2 == 1,
SomeDateValue = this.RandomDay(),
SomeIntValue = this._random.Next(),
SomeString = Guid.NewGuid().ToString(),
SubClasses = new List<IExampleInterface>
{
new ExampleImplementation
{
SomeBooleanValue = this._random.Next() % 2 == 1,
SomeDateValue = this.RandomDay(),
SomeIntValue = this._random.Next(),
SomeString = Guid.NewGuid().ToString(),
SubClasses = new List<IExampleInterface>
{
new ExampleImplementation
{
SomeBooleanValue =
this._random.Next() % 2 == 1,
SomeDateValue = this.RandomDay(),
SomeIntValue = this._random.Next(),
SomeString = Guid.NewGuid().ToString()
}
}
}
}
};
}
public IExampleInterface ObjectToBind
{
get { return this._objectToBind; }
set
{
if (this._objectToBind != value)
{
this._objectToBind = value;
this.OnPropertyChanged("ObjectToBind");
}
}
}
private DateTime RandomDay()
{
var start = new DateTime(1995, 1, 1);
var range = (DateTime.Today - start).Days;
return start.AddDays(this._random.Next(range));
}
}
IExampleInterface(稍后应在实际接口上):
public interface IExampleInterface
{
string SomeString { get; set; }
int SomeIntValue { get; set; }
double SomeDouble { get; set; }
IList<IExampleInterface> SubClasses { get; set; }
IList<IExampleInterface> SubClasses2 { get; set; }
bool SomeBooleanValue { get; set; }
DateTime SomeDateValue { get; set; }
SomeEnum SomeEnumValue { get; set; }
}
ExampleImplementation(稍后应该在具有其他属性的Real Implementation上)。
public class ExampleImplementation : BindableBase, IExampleInterface
{
private bool _someBooleanValue;
private DateTime _someDateValue;
private double _someDouble;
private SomeEnum _someEnumValue;
private int _someIntValue;
private string _someString;
private ObservableCollection<IExampleInterface> _subClasses;
private ObservableCollection<IExampleInterface> _subClasses2;
public bool SomeBooleanValue
{
get { return this._someBooleanValue; }
set
{
if (this._someBooleanValue != value)
{
this._someBooleanValue = value;
this.OnPropertyChanged("SomeBooleanValue");
}
}
}
public DateTime SomeDateValue
{
get { return this._someDateValue; }
set
{
if (this._someDateValue != value)
{
this._someDateValue = value;
this.OnPropertyChanged("SomeDateValue");
}
}
}
public double SomeDouble
{
get { return this._someDouble; }
set
{
if (Math.Abs(this._someDouble - value) > 0.01)
{
this._someDouble = value;
this.OnPropertyChanged("SomeDouble");
}
}
}
public SomeEnum SomeEnumValue
{
get { return this._someEnumValue; }
set
{
if (this._someEnumValue != value)
{
this._someEnumValue = value;
this.OnPropertyChanged("SomeEnumValue");
}
}
}
public int SomeIntValue
{
get { return this._someIntValue; }
set
{
if (this._someIntValue != value)
{
this._someIntValue = value;
this.OnPropertyChanged("SomeIntValue");
}
}
}
[Display(Name = @"TestString", GroupName = @"TestGroup", Description = @"TestDescription")]
public string SomeString
{
get { return this._someString; }
set
{
if (this._someString != value)
{
this._someString = value;
this.OnPropertyChanged("SomeString");
}
}
}
[Display(Name = @"Some Subclasses")]
public IList<IExampleInterface> SubClasses
{
get { return this._subClasses; }
set
{
if (!Equals(this._subClasses, value))
{
this._subClasses = new ObservableCollection<IExampleInterface>(value);
this.OnPropertyChanged("SubClasses");
}
}
}
public IList<IExampleInterface> SubClasses2
{
get { return this._subClasses2; }
set
{
if (!Equals(this._subClasses2, value))
{
this._subClasses2 = new ObservableCollection<IExampleInterface>(value);
this.OnPropertyChanged("SubClasses2");
}
}
}
}
最后是TemplateSelector
public class TemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var def = item as PropertyDefinition;
if (def == null || def.SourceProperty == null)
{
return base.SelectTemplate(item, container);
}
if (typeof (IEnumerable).IsAssignableFrom(def.SourceProperty.PropertyType) && typeof(string) != def.SourceProperty.PropertyType)
{
return this.CollectionsDataTemplate;
}
if (typeof (double).IsAssignableFrom(def.SourceProperty.PropertyType))
{
return this.FloatNumberTemplate;
}
if (typeof (int).IsAssignableFrom(def.SourceProperty.PropertyType))
{
return this.IntNumberTemplate;
}
return base.SelectTemplate(item, container);
}
public DataTemplate CollectionsDataTemplate { get; set; }
public DataTemplate FloatNumberTemplate { get; set; }
public DataTemplate IntNumberTemplate { get; set; }
}
How JVM stack, heap and threads are mapped to physical memory or operation system
最佳解决方案是在TextBlock中获取详细信息,如第1项,第2项等。
谢谢。
//编辑: 我已经找到了NullReferenceException并得到了一个Demo,因此我可以修改文本。但弹出窗口与默认设置不同。你有想法解决它吗?
我已经更新了文字和示例。
答案 0 :(得分:0)
现在浪费了几个小时后,我想出了一个解决方案来实现这个目标。
我已在Collection模板中添加了自定义行为。此行为会在加载或更新后立即设置CollectionEditor的标头。
您可以在下面看到我的修改:
模板:
<model:TemplateSelector.CollectionsDataTemplate>
<DataTemplate>
<telerik:RadDropDownButton Content="Click to edit the collection">
<telerik:RadDropDownButton.DropDownContent>
<telerik:CollectionEditor telerik:AutoBindBehavior.UpdateBindingOnElementLoaded="Source"
ResizeGripperVisibility="Visible">
<i:Interaction.Behaviors>
<model:CollectionEditorBehavior />
</i:Interaction.Behaviors>
</telerik:CollectionEditor>
</telerik:RadDropDownButton.DropDownContent>
</telerik:RadDropDownButton>
</DataTemplate>
</model:TemplateSelector.CollectionsDataTemplate>
行为:
internal class CollectionEditorBehavior : Behavior<CollectionEditor>
{
protected override void OnAttached()
{
this.AssociatedObject.SourceUpdated += (sender, args) => this.PrepareHeader();
this.AssociatedObject.DataContextChanged += (sender, args) => this.PrepareHeader();
this.AssociatedObject.Loaded += (sender, args) => this.PrepareHeader();
}
private void PrepareHeader()
{
if (this.AssociatedObject == null)
{
// Error Case
return;
}
if (this.AssociatedObject.CollectionView == null ||
this.AssociatedObject.CollectionView.SourceCollection == null)
{
// Source not set
this.AssociatedObject.Header = "Collection";
return;
}
// Get the property from the DataContext to retrieve HeaderInformation
var propInfo = this.AssociatedObject.DataContext
.GetType()
.GetProperties()
.FirstOrDefault(
propertyInfo =>
Equals(propertyInfo.GetValue(this.AssociatedObject.DataContext),
this.AssociatedObject.CollectionView.SourceCollection));
if (propInfo == null)
{
// We didn't got the property Information, using default value
this.AssociatedObject.Header = "Collection";
return;
}
// Getting the DisplayName Attribute
var attr = Attribute.GetCustomAttribute(propInfo,
typeof (DisplayNameAttribute)) as DisplayNameAttribute;
if (attr != null)
{
// We have a DisplayName attribute
this.AssociatedObject.Header = attr.DisplayName;
return;
}
// Alternative: Get the Display Attribute
var attr2 = Attribute.GetCustomAttribute(propInfo,
typeof (DisplayAttribute)) as DisplayAttribute;
if (attr2 != null)
{
// We have the Display Attribute
this.AssociatedObject.Header = attr2.Name;
return;
}
// We have no DisplayAttribute and no DisplayName attribute, set it to the PropertyName
this.AssociatedObject.Header = propInfo.Name;
}
}